package com.iplant.mes.serviceImpl;

import com.alibaba.fastjson.JSON;
import com.iplant.ams.service.basicenum.ams.fxt.AMSFrockType;
import com.iplant.ams.service.po.ams.fxt.DMSFrockLedger;
import com.iplant.ams.service.po.dms.DMSDeviceLedger;
import com.iplant.ams.service.po.dms.scada.conf.DMSDeviceParameter;
import com.iplant.ams.service.po.dms.scada.record.DMSProcessRecord;
import com.iplant.ams.serviceImpl.DMSServiceImpl;
import com.iplant.aps.service.apsenum.aps.APSFirstCheckStatus;
import com.iplant.aps.service.po.aps.APSTaskPart;
import com.iplant.aps.service.po.aps.APSTaskPartPoint;
import com.iplant.aps.service.po.aps.APSTaskPartPointDay;
import com.iplant.aps.service.po.oms.OMSOrder;
import com.iplant.base.po.OutResult;
import com.iplant.base.po.Pagination;
import com.iplant.base.po.ServiceResult;
import com.iplant.base.po.enums.ExceptionTypes;
import com.iplant.base.po.excel.ExcelCellData;
import com.iplant.base.po.excel.MyExcelSheet;
import com.iplant.base.utils.general.CalendarTool;
import com.iplant.base.utils.general.Configuration;
import com.iplant.base.utils.general.DesUtil;
import com.iplant.base.utils.general.StringUtils;
import com.iplant.base.utils.sql.orm.ORMUtils;
import com.iplant.base.utils.sql.orm.PoService;
import com.iplant.base.utils.tasker.TaskTimerUtils;
import com.iplant.basic.service.basicenum.bfc.FMCShiftType;
import com.iplant.basic.service.po.bfc.BFCSystemConfig;
import com.iplant.basic.service.po.bms.BMSClassInfo;
import com.iplant.basic.service.po.bms.BMSClassRange;
import com.iplant.basic.service.po.bms.BMSEmployee;
import com.iplant.basic.service.po.fmc.FMCCodeScanningGunConfig;
import com.iplant.basic.service.po.fmc.FMCIPConfig;
import com.iplant.basic.service.po.fmc.FMCStation;
import com.iplant.basic.utils.Constants;
import com.iplant.basic.utils.ExcelUtil;
import com.iplant.mes.service.SFCFrockBindService;
import com.iplant.mes.service.mesenum.sfc.*;
import com.iplant.mes.service.po.bcm.BCMRule;
import com.iplant.mes.service.po.bcm.BCMRuleCode;
import com.iplant.mes.service.po.constants.MESConstants;
import com.iplant.mes.service.po.exc.EXCLineStop;
import com.iplant.mes.service.po.exc.EXCProductRepair;
import com.iplant.mes.service.po.exc.EXCProductRepairItem;
import com.iplant.mes.service.po.ipt.IPTValue;
import com.iplant.mes.service.po.print.SFCFactoryTest;
import com.iplant.mes.service.po.print.SFCFactoryTestCode;
import com.iplant.mes.service.po.print.SFCFactoryTestItem;
import com.iplant.mes.service.po.sfc.*;
import com.iplant.mes.service.po.sfc.frockBind.SFCBindComponent;
import com.iplant.mes.service.po.sfc.workpieceRecord.SFCExportHead;
import com.iplant.mes.serviceImpl.dao.ipt.IPTValueDAO;
import com.iplant.mes.serviceImpl.dao.sfc.SFCWorkpieceRecordDAO;
import com.iplant.pdm.service.basicenum.fpc.FPCCheckType;
import com.iplant.pdm.service.basicenum.fpc.FPCParamType;
import com.iplant.pdm.service.basicenum.fpc.FPCTaskReportMode;
import com.iplant.pdm.service.basicenum.pdm.PDMComponentTypes;
import com.iplant.pdm.service.po.bop.FPCRoutePartPoint;
import com.iplant.pdm.service.po.bop.partpoint.FPCRoutePartPointParameter;
import com.iplant.pdm.service.po.bop.partpoint.FPCRouteStep;
import com.iplant.pdm.service.po.fpc.FPCProduct;
import com.iplant.pdm.service.po.fpc.FPCProductCom;
import com.iplant.pdm.service.po.mss.MSSBOMItem;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.stereotype.Service;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SFCFrockBindServiceImpl implements SFCFrockBindService {

    //region 构造函数
    public SFCFrockBindServiceImpl() {
    }
    //endregion

    //region 单实例

    private static SFCFrockBindService Instance = null;

    public static SFCFrockBindService getInstance() {
        if (Instance == null)
            Instance = new SFCFrockBindServiceImpl();

        return Instance;
    }

    //endregion

    //region POService
    PoService<SFCTaskSelf> mSFCTaskSelfService = ORMUtils.GetPoService(SFCTaskSelf.class);
    PoService<APSTaskPartPointDay> mAPSTaskPartPointDayService = ORMUtils.GetPoService(APSTaskPartPointDay.class);
    PoService<SFCLoginEvent> mSFCLoginEventService = ORMUtils.GetPoService(SFCLoginEvent.class);
    PoService<SFCTaskIPT> mSFCTaskIPTService = ORMUtils.GetPoService(SFCTaskIPT.class);
    PoService<BMSClassRange> mBMSClassRangeService = ORMUtils.GetPoService(BMSClassRange.class);
    PoService<FPCRouteStep> mFPCRouteStepService = ORMUtils.GetPoService(FPCRouteStep.class);
    PoService<IPTValue> mIPTValueService = ORMUtils.GetPoService(IPTValue.class);
    PoService<FPCRoutePartPoint> mFPCRoutePartPointService = ORMUtils.GetPoService(FPCRoutePartPoint.class);
    PoService<SFCWorkpieceRecord> mSFCWorkpieceRecordService = ORMUtils.GetPoService(SFCWorkpieceRecord.class);
    PoService<SFCTaskReport> mSFCTaskReportService = ORMUtils.GetPoService(SFCTaskReport.class);
    PoService<APSTaskPartPoint> mAPSTaskPartPointService = ORMUtils.GetPoService(APSTaskPartPoint.class);
    PoService<APSTaskPart> mAPSTaskPartService = ORMUtils.GetPoService(APSTaskPart.class);
    PoService<SFCFrockBindRecord> mSFCFrockBindRecordService = ORMUtils.GetPoService(SFCFrockBindRecord.class);
    PoService<MSSBOMItem> mMSSBOMItemService = ORMUtils.GetPoService(MSSBOMItem.class);
    PoService<SFCStationMaterial> mSFCStationMaterialService = ORMUtils.GetPoService(SFCStationMaterial.class);
    PoService<SFCBoxReport> mSFCBoxReportService = ORMUtils.GetPoService(SFCBoxReport.class);
    PoService<OMSOrder> mOMSOrderService = ORMUtils.GetPoService(OMSOrder.class);
    PoService<DMSFrockLedger> mDMSFrockLedgerService = ORMUtils.GetPoService(DMSFrockLedger.class);
    PoService<DMSDeviceLedger> mDMSDeviceLedgerService = ORMUtils.GetPoService(DMSDeviceLedger.class);
    PoService<SFCWorkpieceResume> mSFCWorkpieceResumeService = ORMUtils.GetPoService(SFCWorkpieceResume.class);
    PoService<SFCMaterialLoadingRecord> mSFCMaterialLoadingRecordService =
            ORMUtils.GetPoService(SFCMaterialLoadingRecord.class);
    PoService<SFCTaskStartCheck> mSFCTaskStartCheckService = ORMUtils.GetPoService(SFCTaskStartCheck.class);
    PoService<BMSClassInfo> mBMSClassInfoService = ORMUtils.GetPoService(BMSClassInfo.class);

    PoService<FMCStation> mFMCStationService = ORMUtils.GetPoService(FMCStation.class);
    PoService<FMCIPConfig> mFMCIPConfigService = ORMUtils.GetPoService(FMCIPConfig.class);
    PoService<FMCCodeScanningGunConfig> mFMCCodeScanningGunConfigService =
            ORMUtils.GetPoService(FMCCodeScanningGunConfig.class);
    PoService<SFCAssemblyRecord> mSFCAssemblyRecordService =
            ORMUtils.GetPoService(SFCAssemblyRecord.class);
    PoService<EXCProductRepairItem> mEXCProductRepairItemService =
            ORMUtils.GetPoService(EXCProductRepairItem.class);
    PoService<EXCProductRepair> mEXCProductRepairService = ORMUtils.GetPoService(EXCProductRepair.class);
    PoService<FPCProductCom> mFPCProductComService = ORMUtils.GetPoService(FPCProductCom.class);
    PoService<SFCTaskParamItem> mSFCTaskParamItemService = ORMUtils.GetPoService(SFCTaskParamItem.class);
    PoService<SFCFactoryTestCode> mSFCFactoryTestCodeService = ORMUtils.GetPoService(SFCFactoryTestCode.class);
    PoService<FPCProduct> mFPCProductService = ORMUtils.GetPoService(FPCProduct.class);
    PoService<BCMRule> mBCMRuleService = ORMUtils.GetPoService(BCMRule.class);
    PoService<EXCLineStop> mEXCLineStopService = ORMUtils.GetPoService(EXCLineStop.class);
    PoService<FPCRoutePartPointParameter> mFPCRoutePartPointParameterService =
            ORMUtils.GetPoService(FPCRoutePartPointParameter.class);
    PoService<DMSDeviceParameter> mDMSDeviceParameterService = ORMUtils.GetPoService(DMSDeviceParameter.class);
    PoService<BFCSystemConfig> mBFCSystemConfigService = ORMUtils.GetPoService(BFCSystemConfig.class);
    PoService<SFCWorkpieceExportRecord> mSFCWorkpieceExportRecordService =
            ORMUtils.GetPoService(SFCWorkpieceExportRecord.class);
    //endregion

    @Override
    public ServiceResult<SFCTaskSelf> SFC_GetWorkOrderByComponentCode(BMSEmployee wLoginUser, String wComponentCode,
                                                                      List<SFCTaskSelf> wSFCTaskSelfList) {
        ServiceResult<SFCTaskSelf> wResult = new ServiceResult<>();
        wResult.Result = new SFCTaskSelf();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①查询工件记录
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("Code", wComponentCode);
            SFCWorkpieceRecord sfcWorkpieceRecord = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (sfcWorkpieceRecord == null || sfcWorkpieceRecord.ID <= 0) {
                wResult.FaultCode += StringUtils.Format("未查询到【{0}】的工件记录", wComponentCode);
                return wResult;
            }
            //②根据工件订单获取工单
            if (wSFCTaskSelfList.stream().noneMatch(p -> p.OrderID == sfcWorkpieceRecord.OrderID)) {
                wResult.FaultCode += StringUtils.Format("工件【{0}】绑定的订单未开工", wComponentCode);
                return wResult;
            }

            SFCTaskSelf sfcTaskSelf =
                    wSFCTaskSelfList.stream().filter(p -> p.OrderID == sfcWorkpieceRecord.OrderID).findFirst().get();
            //③查询工单上道工序
            wParams.clear();
            wParams.put("ID", sfcTaskSelf.RoutePartPointID);
            FPCRoutePartPoint fpcRoutePartPoint = mFPCRoutePartPointService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (fpcRoutePartPoint == null || fpcRoutePartPoint.ID <= 0) {
                wResult.FaultCode += StringUtils.Format("工艺数据缺失，请联系系统管理员");
                return wResult;
            }

            if (fpcRoutePartPoint.PrevPartPointID > 0) {
                wParams.clear();
                wParams.put("ID", fpcRoutePartPoint.PrevPartPointID);
                FPCRoutePartPoint fpcRoutePartPoint1 = mFPCRoutePartPointService.SelectPO(wLoginUser, wParams,
                        wErrorCode);

                //④判断工件上单工序是否已做，若未做则报错
                wParams.clear();
                wParams.put("OrderID", sfcTaskSelf.OrderID);
                wParams.put("Active", 1);
                wParams.put("RoutePartPointID", fpcRoutePartPoint.PrevPartPointID);
                wParams.put("Type", FPCCheckType.SELF_CHECK.getValue());
                wParams.put("ComponentCode", wComponentCode);
                List<SFCTaskIPT> sfcTaskIPTS = mSFCTaskIPTService.SelectPOList(wLoginUser, wParams,
                        Pagination.getNewMaxSize(),
                        wErrorCode);
                if (sfcTaskIPTS.size() <= 0 && fpcRoutePartPoint1.ReportMode != SFCTaskReportMode.NUMBER_REPORT.getValue()) {
                    wResult.FaultCode += StringUtils.Format("工件【{0}】未做上道工序【{1}】的自检!", wComponentCode,
                            fpcRoutePartPoint1.Name);
                    return wResult;
                }
            }

            //⑤返回前端
            wResult.Result = sfcTaskSelf;

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_GetWorkOrderByComponentCode", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_TrayBindingWorkOrder(BMSEmployee wLoginUser, String wTrayCode,
                                                           List<SFCBindComponent> wSFCBindComponentList, int wStatus) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①验证托盘是否存在
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("CodeEQ", wTrayCode);
            DMSFrockLedger wDMSFrockLedger = mDMSFrockLedgerService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (wDMSFrockLedger == null || wDMSFrockLedger.ID <= 0 || wDMSFrockLedger.FrockType != AMSFrockType.TP.getValue()) {
                wResult.FaultCode += StringUtils.Format("托盘码【{0}】错误!", wTrayCode);
                return wResult;
            }
            //②验证托盘是否已绑定
            wParams.clear();
            wParams.put("FrockLedgerCode", wTrayCode);
            wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
            List<SFCFrockBindRecord> sfcFrockBindRecords = mSFCFrockBindRecordService.SelectPOList(wLoginUser,
                    wParams, Pagination.getNewMaxSize(),
                    wErrorCode);
            if (sfcFrockBindRecords.size() > 0) {
                wResult.FaultCode += StringUtils.Format("托盘【{0}】绑定失败，该托盘已被使用，需要解绑后才能再次使用!", wTrayCode);
                return wResult;
            }
            //③验证工单是否已绑定
            for (SFCBindComponent sfcBindComponent : wSFCBindComponentList) {
                wParams.clear();
                wParams.put("WorkOrderID", sfcBindComponent.TaskSelfID);
                wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
                List<SFCFrockBindRecord> sfcFrockBindRecords1 = mSFCFrockBindRecordService.SelectPOList(wLoginUser,
                        wParams, Pagination.getNewMaxSize(),
                        wErrorCode);
                if (sfcFrockBindRecords1.size() > 0) {
                    wResult.FaultCode += StringUtils.Format("工单【{0}】已绑定!", sfcBindComponent.TaskSelfCode);
                    return wResult;
                }
            }
            //④验证工单的工艺参数是否相同
            if (wSFCBindComponentList.size() > 1) {
                wParams.clear();
                List<Integer> wTaskSelfIDList =
                        wSFCBindComponentList.stream().map(p -> p.TaskSelfID).distinct().collect(Collectors.toList());
                List<SFCTaskSelf> sfcTaskSelves = mSFCTaskSelfService.SelectPOList(wLoginUser, wTaskSelfIDList,
                        wParams, Pagination.getNewMaxSize(),
                        wErrorCode);
                //查询工序列表
                List<Integer> wRoutePartPointIDList =
                        sfcTaskSelves.stream().map(p -> p.RoutePartPointID).distinct().collect(Collectors.toList());
                wParams.clear();
                List<FPCRoutePartPoint> fpcRoutePartPoints = mFPCRoutePartPointService.SelectPOList(wLoginUser,
                        wRoutePartPointIDList, wParams, Pagination.getNewMaxSize(),
                        wErrorCode);
                //判断工单对应工序是否有下道工序，若没有，无法比较工艺参数
                for (SFCTaskSelf sfcTaskSelf : sfcTaskSelves) {
                    if (fpcRoutePartPoints.stream().noneMatch(p -> p.ID == sfcTaskSelf.RoutePartPointID && p.NextPartPointID != null && p.NextPartPointID.size() > 0)) {
                        wResult.FaultCode += StringUtils.Format("工单【{0}】-工序【{1}】未配置下道工序!", sfcTaskSelf.Code,
                                sfcTaskSelf.RoutePartPointName);
                        return wResult;
                    }
                }
                //获取下道工序
                List<Integer> wNextIDList = new ArrayList<>();
                for (FPCRoutePartPoint fpcRoutePartPoint : fpcRoutePartPoints) {
                    if (fpcRoutePartPoint.NextPartPointID != null && fpcRoutePartPoint.NextPartPointID.size() > 0) {
                        wNextIDList.add(fpcRoutePartPoint.NextPartPointID.get(0));
                    }
                }
                //工艺参数列表
                if (wNextIDList.size() > 1) {
                    String wRoutePartPointIDs = StringUtils.Join(",",
                            wNextIDList);
                    wParams.clear();
                    wParams.put("RoutePartPointID", wRoutePartPointIDs);
                    wParams.put("Active", 1);
                    wParams.put("ParamType", FPCParamType.PROCESS_PARAMETERS.getValue());
                    List<FPCRoutePartPointParameter> fpcRoutePartPointParameters =
                            mFPCRoutePartPointParameterService.SelectPOList(wLoginUser, wParams,
                                    Pagination.getNewMaxSize(),
                                    wErrorCode);
                    fpcRoutePartPointParameters =
                            fpcRoutePartPointParameters.stream().filter(p -> StringUtils.isNotEmpty(p.CollectionNumber)).collect(Collectors.toList());
                    if (fpcRoutePartPointParameters.size() > 0) {
                        String wMsg = CheckTechParamsIsSame(wLoginUser, wNextIDList,
                                fpcRoutePartPointParameters, wErrorCode);
                        if (StringUtils.isNotEmpty(wMsg)) {
                            wResult.FaultCode = wMsg;
                            return wResult;
                        }
                    }
                }
            }
            //⑤托盘绑定工单
            SFCFrockBindRecord wSFCFrockBindRecord;
            for (SFCBindComponent sfcBindComponent : wSFCBindComponentList) {
                wSFCFrockBindRecord = new SFCFrockBindRecord();
                wSFCFrockBindRecord.setUserInfo(wLoginUser);
                wSFCFrockBindRecord.ComponentCode = sfcBindComponent.ComponentCode;
                wSFCFrockBindRecord.WorkOrderID = sfcBindComponent.TaskSelfID;
                wSFCFrockBindRecord.Status = wStatus;
                wSFCFrockBindRecord.ComponentType = PDMComponentTypes.WorkOrder.getValue();
                wSFCFrockBindRecord.FrockLedgerID = wDMSFrockLedger.ID;
                wSFCFrockBindRecord.FrockLedgerCode = wDMSFrockLedger.Code;
                wSFCFrockBindRecord.Number = sfcBindComponent.Number;
                wSFCFrockBindRecord.Active = 1;
                mSFCFrockBindRecordService.UpdatePo(wLoginUser, wSFCFrockBindRecord, wErrorCode);
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_TrayBindingWorkOrder", e);
        }
        return wResult;
    }

    /**
     * 判断工艺参数是否相同
     */
    private String CheckTechParamsIsSame(BMSEmployee wLoginUser,
                                         List<Integer> wRoutePartPointIDList,
                                         List<FPCRoutePartPointParameter> fpcRoutePartPointParameters,
                                         OutResult<Integer> wErrorCode) {
        String wResult = "";
        try {
            List<FPCRoutePartPointParameter> wList;
            List<FPCRoutePartPointParameter> wOtherList;
            for (int wRoutePartPointID : wRoutePartPointIDList) {
                wList =
                        fpcRoutePartPointParameters.stream().filter(p -> p.RoutePartPointID == wRoutePartPointID).collect(Collectors.toList());
                for (FPCRoutePartPointParameter fpcRoutePartPointParameter : wList) {
                    //判断其他工艺的工艺参数是否有相同的参数
                    List<Integer> wOtherIDList =
                            wRoutePartPointIDList.stream().filter(p -> p != wRoutePartPointID).collect(Collectors.toList());
                    for (int wOtherRoutePartPointID : wOtherIDList) {
                        wOtherList =
                                fpcRoutePartPointParameters.stream().filter(p -> p.RoutePartPointID == wOtherRoutePartPointID).collect(Collectors.toList());
                        if (wOtherList.stream().noneMatch(p -> p.CollectionNumber.equals(fpcRoutePartPointParameter.CollectionNumber) && p.StandardLeft == fpcRoutePartPointParameter.StandardLeft
                                && p.StandardRight == fpcRoutePartPointParameter.StandardRight
                                && p.StandardType == fpcRoutePartPointParameter.StandardType)) {
                            wResult = StringUtils.Format("工序【{0}】-工艺参数【{1}】标准不一致",
                                    fpcRoutePartPointParameter.RoutePartPointName,
                                    fpcRoutePartPointParameter.ParamName);
                            return wResult;
                        }
                    }
                }
            }
        } catch (Exception ex) {
            log.error("CheckTechParamsIsSame", ex);
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> SFC_ExportDeviceRecord(BMSEmployee wLoginUser, String wWorkpieceNo, int wRoutePartID
            , int wRoutePartPointID, int wDeviceID, List<SFCExportHead> wHeadList, String wDeviceName) {
        ServiceResult<String> wResult = new ServiceResult<>();
        wResult.Result = "";
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            List<Map<String, Object>> wDataList = SFCServiceImpl.getInstance().QueryDeviceRecord(wLoginUser,
                    wWorkpieceNo,
                    wRoutePartID, wRoutePartPointID, -1, wDeviceID).Result;
            if (wDataList == null || wDataList.size() <= 0) {
                wResult.FaultCode += "导出失败：无数据!";
                return wResult;
            }

            MyExcelSheet wMyExcelSheet = this.GetMyExcelSheet_ExportDeviceRecord(wHeadList, wDataList, wDeviceName);

            List<MyExcelSheet> wMyExcelSheetList =
                    new ArrayList<MyExcelSheet>(Collections.singletonList(wMyExcelSheet));

            wResult.Result = ExcelUtil.ExportData(wMyExcelSheetList, StringUtils.Format("设备【{0}】实时参数", wDeviceName));

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_ExportDeviceRecord", e);
        }
        return wResult;
    }

    /**
     * 整理导出数据
     */
    private MyExcelSheet GetMyExcelSheet_ExportDeviceRecord(List<SFCExportHead> wHeadList,
                                                            List<Map<String, Object>> wDataList, String wDeviceName) {
        MyExcelSheet wResult = new MyExcelSheet();
        try {
            wResult.SheetName = StringUtils.Format("设备【{0}】实时参数", wDeviceName);
            wResult.TitleName = StringUtils.Format("设备【{0}】实时参数", wDeviceName);
            wResult.HeaderList = new ArrayList<>(Arrays.asList("序号", "发生时间"));
            wResult.HeaderList.addAll(wHeadList.stream().map(p -> p.label).collect(Collectors.toList()));
            wResult.DataList = new ArrayList<>();
            List<String> wValueList;
            int wIndex = 1;
            for (Map<String, Object> stringObjectMap : wDataList) {
                wValueList = new ArrayList<>();
                //序号
                wValueList.add(String.valueOf(wIndex++));
                //发生时间
                if (stringObjectMap.containsKey("CreateTime")) {
                    wValueList.add(stringObjectMap.get("CreateTime").toString());
                } else {
                    wValueList.add("");
                }
                //动态参数
                for (SFCExportHead wSFCExportHead : wHeadList) {
                    if (stringObjectMap.containsKey(wSFCExportHead.prop)) {
                        wValueList.add(String.valueOf(stringObjectMap.get(wSFCExportHead.prop)));
                    } else {
                        wValueList.add("0");
                    }
                }

                wResult.DataList.add(wValueList);
            }
        } catch (Exception ex) {
            log.error("GetMyExcelSheet_ExportDeviceRecord", ex);
        }
        return wResult;
    }

    @Override
    public void UpdateWorkpieceRelaCode(BMSEmployee wLoginUser, List<SFCAssemblyRecord> wToBindList) {
        try {
            if (wToBindList == null || wToBindList.size() <= 0) {
                return;
            }

            OutResult<Integer> wErrorCode = new OutResult<Integer>(0);
            Map<String, Object> wParams = new HashMap<String, Object>();

            for (SFCAssemblyRecord wSFCAssemblyRecord : wToBindList) {
                //①元件组装成芯子，更新元件记录的芯子码
                if (wSFCAssemblyRecord.TargetComponentType == PDMComponentTypes.Core.getValue()) {
                    wParams.clear();
                    wParams.put("Code", wSFCAssemblyRecord.SourceCode);
                    SFCWorkpieceRecord sfcWorkpieceRecord = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                            wErrorCode);
                    if (sfcWorkpieceRecord != null && sfcWorkpieceRecord.ID > 0
                            && sfcWorkpieceRecord.ComponentType == PDMComponentTypes.Component.getValue()) {
                        sfcWorkpieceRecord.CaseNo = wSFCAssemblyRecord.TargetCode;
                        mSFCWorkpieceRecordService.UpdatePo(wLoginUser, sfcWorkpieceRecord, wErrorCode);
                    }
                }
                //②芯子组装成成品，更新芯子记录的成品码，更新元件记录的成品码
                else if (wSFCAssemblyRecord.TargetComponentType == PDMComponentTypes.Product.getValue()) {
                    wParams.clear();
                    wParams.put("Code", wSFCAssemblyRecord.SourceCode);
                    SFCWorkpieceRecord sfcWorkpieceRecord = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                            wErrorCode);
                    if (sfcWorkpieceRecord != null && sfcWorkpieceRecord.ID > 0
                            && sfcWorkpieceRecord.ComponentType == PDMComponentTypes.Core.getValue()) {
                        sfcWorkpieceRecord.PackageNo = wSFCAssemblyRecord.TargetCode;
                        mSFCWorkpieceRecordService.UpdatePo(wLoginUser, sfcWorkpieceRecord, wErrorCode);
                    }
                    //更新元件的成品码
                    wParams.clear();
                    wParams.put("CaseNo", wSFCAssemblyRecord.SourceCode);
                    wParams.put("ComponentType", PDMComponentTypes.Component.getValue());
                    List<SFCWorkpieceRecord> sfcWorkpieceRecords = mSFCWorkpieceRecordService.SelectPOList(wLoginUser
                            , wParams, Pagination.getNewMaxSize(),
                            wErrorCode);
                    for (SFCWorkpieceRecord workpieceRecord : sfcWorkpieceRecords) {
                        workpieceRecord.PackageNo = wSFCAssemblyRecord.TargetCode;
                        mSFCWorkpieceRecordService.UpdatePo(wLoginUser, workpieceRecord, wErrorCode);
                    }
                }
                //③成品组装成箱体，更新成品记录的箱体码，更新芯子记录的箱体码，更新元件记录的箱体码
                else if (wSFCAssemblyRecord.TargetComponentType == PDMComponentTypes.Box.getValue()) {
                    wParams.clear();
                    wParams.put("Code", wSFCAssemblyRecord.SourceCode);
                    SFCWorkpieceRecord sfcWorkpieceRecord = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                            wErrorCode);
                    if (sfcWorkpieceRecord != null && sfcWorkpieceRecord.ID > 0
                            && sfcWorkpieceRecord.ComponentType == PDMComponentTypes.Product.getValue()) {
                        sfcWorkpieceRecord.BoxNo = wSFCAssemblyRecord.TargetCode;
                        mSFCWorkpieceRecordService.UpdatePo(wLoginUser, sfcWorkpieceRecord, wErrorCode);
                    }
                    //更新芯子记录的箱体码
                    wParams.clear();
                    wParams.put("PackageNo", wSFCAssemblyRecord.SourceCode);
                    wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                    List<SFCWorkpieceRecord> sfcWorkpieceRecords = mSFCWorkpieceRecordService.SelectPOList(wLoginUser
                            , wParams, Pagination.getNewMaxSize(),
                            wErrorCode);
                    for (SFCWorkpieceRecord workpieceRecord : sfcWorkpieceRecords) {
                        workpieceRecord.BoxNo = wSFCAssemblyRecord.TargetCode;
                        mSFCWorkpieceRecordService.UpdatePo(wLoginUser, workpieceRecord, wErrorCode);
                        //更新元件记录的箱体码
                        wParams.clear();
                        wParams.put("CaseNo", workpieceRecord.Code);
                        wParams.put("ComponentType", PDMComponentTypes.Component.getValue());
                        List<SFCWorkpieceRecord> sfcWorkpieceRecords1 =
                                mSFCWorkpieceRecordService.SelectPOList(wLoginUser
                                        , wParams, Pagination.getNewMaxSize(),
                                        wErrorCode);
                        for (SFCWorkpieceRecord record : sfcWorkpieceRecords1) {
                            record.BoxNo = wSFCAssemblyRecord.TargetCode;
                            mSFCWorkpieceRecordService.UpdatePo(wLoginUser, record, wErrorCode);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            log.error("UpdateWorkpieceRelaCode", ex);
        }
    }

    @Override
    public void SFC_WorkpieceRecordSubScrap(BMSEmployee wLoginUser, SFCWorkpieceRecord wSFCWorkpieceRecord,
                                            OutResult<Integer> wErrorCode) {
        try {
            Map<String, Object> wParams = new HashMap<String, Object>();

            //箱体报废，成品、芯子、元件报废
            if (wSFCWorkpieceRecord.ComponentType == PDMComponentTypes.Box.getValue()) {
                //成品报废
                wParams.put("BoxNo", wSFCWorkpieceRecord.Code);
                wParams.put("ComponentType", PDMComponentTypes.Product.getValue());
                List<SFCWorkpieceRecord> sfcWorkpieceRecords = mSFCWorkpieceRecordService.SelectPOList(wLoginUser,
                        wParams, Pagination.getNewMaxSize(),
                        wErrorCode);
                for (SFCWorkpieceRecord sfcWorkpieceRecord : sfcWorkpieceRecords) {
                    sfcWorkpieceRecord.Status = wSFCWorkpieceRecord.Status;
                    sfcWorkpieceRecord.ScarpID = wSFCWorkpieceRecord.ScarpID;
                    sfcWorkpieceRecord.ScarpTime = wSFCWorkpieceRecord.ScarpTime;
                    sfcWorkpieceRecord.ScarpReason = wSFCWorkpieceRecord.ScarpReason;
                    mSFCWorkpieceRecordService.UpdatePo(wLoginUser, sfcWorkpieceRecord, wErrorCode);
                    //芯子报废
                    wParams.clear();
                    wParams.put("PackageNo", sfcWorkpieceRecord.Code);
                    wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                    List<SFCWorkpieceRecord> sfcWorkpieceRecords1 = mSFCWorkpieceRecordService.SelectPOList(wLoginUser,
                            wParams, Pagination.getNewMaxSize(),
                            wErrorCode);
                    for (SFCWorkpieceRecord workpieceRecord : sfcWorkpieceRecords1) {
                        workpieceRecord.Status = wSFCWorkpieceRecord.Status;
                        workpieceRecord.ScarpID = wSFCWorkpieceRecord.ScarpID;
                        workpieceRecord.ScarpTime = wSFCWorkpieceRecord.ScarpTime;
                        workpieceRecord.ScarpReason = wSFCWorkpieceRecord.ScarpReason;
                        mSFCWorkpieceRecordService.UpdatePo(wLoginUser, workpieceRecord, wErrorCode);
                        //元件报废
                        wParams.clear();
                        wParams.put("CaseNo", workpieceRecord.Code);
                        wParams.put("ComponentType", PDMComponentTypes.Component.getValue());
                        List<SFCWorkpieceRecord> sfcWorkpieceRecords2 =
                                mSFCWorkpieceRecordService.SelectPOList(wLoginUser,
                                        wParams, Pagination.getNewMaxSize(),
                                        wErrorCode);
                        for (SFCWorkpieceRecord record : sfcWorkpieceRecords2) {
                            record.Status = wSFCWorkpieceRecord.Status;
                            record.ScarpID = wSFCWorkpieceRecord.ScarpID;
                            record.ScarpTime = wSFCWorkpieceRecord.ScarpTime;
                            record.ScarpReason = wSFCWorkpieceRecord.ScarpReason;
                            mSFCWorkpieceRecordService.UpdatePo(wLoginUser, record, wErrorCode);
                        }
                    }
                }

            }
            //成品报废，芯子、元件报废
            else if (wSFCWorkpieceRecord.ComponentType == PDMComponentTypes.Product.getValue()) {
                //芯子报废
                wParams.put("PackageNo", wSFCWorkpieceRecord.Code);
                wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                List<SFCWorkpieceRecord> sfcWorkpieceRecords = mSFCWorkpieceRecordService.SelectPOList(wLoginUser,
                        wParams, Pagination.getNewMaxSize(),
                        wErrorCode);
                for (SFCWorkpieceRecord sfcWorkpieceRecord : sfcWorkpieceRecords) {
                    sfcWorkpieceRecord.Status = wSFCWorkpieceRecord.Status;
                    sfcWorkpieceRecord.ScarpID = wSFCWorkpieceRecord.ScarpID;
                    sfcWorkpieceRecord.ScarpTime = wSFCWorkpieceRecord.ScarpTime;
                    sfcWorkpieceRecord.ScarpReason = wSFCWorkpieceRecord.ScarpReason;
                    mSFCWorkpieceRecordService.UpdatePo(wLoginUser, sfcWorkpieceRecord, wErrorCode);
                    //元件报废
                    wParams.clear();
                    wParams.put("CaseNo", sfcWorkpieceRecord.Code);
                    wParams.put("ComponentType", PDMComponentTypes.Component.getValue());
                    List<SFCWorkpieceRecord> sfcWorkpieceRecords1 = mSFCWorkpieceRecordService.SelectPOList(wLoginUser,
                            wParams, Pagination.getNewMaxSize(),
                            wErrorCode);
                    for (SFCWorkpieceRecord workpieceRecord : sfcWorkpieceRecords1) {
                        workpieceRecord.Status = wSFCWorkpieceRecord.Status;
                        workpieceRecord.ScarpID = wSFCWorkpieceRecord.ScarpID;
                        workpieceRecord.ScarpTime = wSFCWorkpieceRecord.ScarpTime;
                        workpieceRecord.ScarpReason = wSFCWorkpieceRecord.ScarpReason;
                        mSFCWorkpieceRecordService.UpdatePo(wLoginUser, workpieceRecord, wErrorCode);
                    }
                }
            }
            //芯子报废，元件报废
            else if (wSFCWorkpieceRecord.ComponentType == PDMComponentTypes.Core.getValue()) {
                wParams.put("CaseNo", wSFCWorkpieceRecord.Code);
                wParams.put("ComponentType", PDMComponentTypes.Component.getValue());
                List<SFCWorkpieceRecord> sfcWorkpieceRecords = mSFCWorkpieceRecordService.SelectPOList(wLoginUser,
                        wParams, Pagination.getNewMaxSize(),
                        wErrorCode);
                for (SFCWorkpieceRecord sfcWorkpieceRecord : sfcWorkpieceRecords) {
                    sfcWorkpieceRecord.Status = wSFCWorkpieceRecord.Status;
                    sfcWorkpieceRecord.ScarpID = wSFCWorkpieceRecord.ScarpID;
                    sfcWorkpieceRecord.ScarpTime = wSFCWorkpieceRecord.ScarpTime;
                    sfcWorkpieceRecord.ScarpReason = wSFCWorkpieceRecord.ScarpReason;
                    mSFCWorkpieceRecordService.UpdatePo(wLoginUser, sfcWorkpieceRecord, wErrorCode);
                }
            }
        } catch (Exception ex) {
            log.error("SFC_WorkpieceRecordSubScrap", ex);
        }
    }

    @Override
    public ServiceResult<List<SFCTaskSelf>> SFC_QueryTaskListByTrayAndStation(BMSEmployee wLoginUser,
                                                                              String wTrayCode, int wStationID) {
        ServiceResult<List<SFCTaskSelf>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①根据托盘查询绑定的工单信息
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("FrockLedgerCode", wTrayCode);
            wParams.put("ComponentType", PDMComponentTypes.WorkOrder.getValue());
            wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
            List<SFCFrockBindRecord> sfcFrockBindRecords = mSFCFrockBindRecordService.SelectPOList(wLoginUser,
                    wParams, Pagination.getNewMaxSize(),
                    wErrorCode);
            if (sfcFrockBindRecords == null || sfcFrockBindRecords.size() <= 0) {
                //查询托盘绑定工件记录
                wParams.clear();
                wParams.put("FrockLedgerCode", wTrayCode);
                wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
                sfcFrockBindRecords = mSFCFrockBindRecordService.SelectPOList(wLoginUser,
                        wParams, Pagination.getNewMaxSize(),
                        wErrorCode);
                if (sfcFrockBindRecords == null || sfcFrockBindRecords.size() <= 0) {
                    wResult.FaultCode += StringUtils.Format("托盘【{0}】未绑定工单或工件!", wTrayCode);
                    return wResult;
                }
            }
            //②根据工单ID查询工单列表
            List<Integer> wOrderIDList = new ArrayList<>();
            if (sfcFrockBindRecords.stream().anyMatch(p -> p.WorkOrderID > 0)) {
                wParams.clear();
                List<Integer> wWorkOrderIDList =
                        sfcFrockBindRecords.stream().map(p -> p.WorkOrderID).distinct().collect(Collectors.toList());
                List<SFCTaskSelf> sfcTaskSelves = mSFCTaskSelfService.SelectPOList(wLoginUser, wWorkOrderIDList,
                        wParams,
                        Pagination.getNewMaxSize(),
                        wErrorCode);
                if (sfcTaskSelves == null || sfcTaskSelves.size() <= 0) {
                    return wResult;
                }
                //③根据订单、工位查询已开工工单列表
                wOrderIDList =
                        sfcTaskSelves.stream().map(p -> p.OrderID).distinct().collect(Collectors.toList());
            } else {
                Optional<SFCFrockBindRecord> first =
                        sfcFrockBindRecords.stream().filter(p -> p.ComponentType == PDMComponentTypes.Component.getValue()
                                || p.ComponentType == PDMComponentTypes.Core.getValue()
                                || p.ComponentType == PDMComponentTypes.Product.getValue()
                                || p.ComponentType == PDMComponentTypes.Box.getValue()).findFirst();
                if (first.isPresent()) {
                    wParams.clear();
                    wParams.put("Code", first.get().ComponentCode);
                    SFCWorkpieceRecord sfcWorkpieceRecord = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                            wErrorCode);
                    if (sfcWorkpieceRecord != null && sfcWorkpieceRecord.ID > 0) {
                        wOrderIDList.add(sfcWorkpieceRecord.OrderID);
                    }
                }
            }

            if (wOrderIDList.size() <= 0) {
                wResult.FaultCode += StringUtils.Format("通过托盘【{0}】获取绑定订单失败!", wTrayCode);
                return wResult;
            }
            String wOrderIDs = StringUtils.Join(",", wOrderIDList);

            wParams.clear();
            wParams.put("OrderID", wOrderIDs);
            wParams.put("StationID", wStationID);
            wParams.put("Active", 1);
            wParams.put("Status", SFCTaskStatus.Doing.getValue());
            //④返回前端
            wResult.Result = mSFCTaskSelfService.SelectPOList(wLoginUser, wParams, Pagination.getNewMaxSize(),
                    wErrorCode);

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_QueryTaskListByTrayAndStation", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCWorkpieceRecord> SFC_QueryProductInfoByTray(BMSEmployee wLoginUser,
                                                                        String wTrayCode, String wMouldCode) {
        ServiceResult<SFCWorkpieceRecord> wResult = new ServiceResult<>();
        wResult.Result = new SFCWorkpieceRecord();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①根据托盘码查询绑定的产品信息
            if (StringUtils.isNotEmpty(wTrayCode)) {
                Map<String, Object> wParams = new HashMap<String, Object>();
                wParams.put("FrockLedgerCode", wTrayCode);
                wParams.put("ComponentType", PDMComponentTypes.Product.getValue());
                wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
                SFCFrockBindRecord sfcFrockBindRecord = mSFCFrockBindRecordService.SelectPO(wLoginUser, wParams,
                        wErrorCode);
                if (sfcFrockBindRecord != null && sfcFrockBindRecord.ID > 0) {
                    //②根据产品码查询工件记录
                    wParams.clear();
                    wParams.put("Code", sfcFrockBindRecord.ComponentCode);
                    //③返回前端
                    wResult.Result = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                            wErrorCode);
                    if (wResult.Result.ID <= 0) {
                        wResult.Result.Code = sfcFrockBindRecord.ComponentCode;
                    }
                } else {
                    //根据托盘码查询芯子码
                    wParams.clear();
                    wParams.put("FrockLedgerCode", wTrayCode);
                    wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                    wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
                    SFCFrockBindRecord sfcFrockBindRecord1 = mSFCFrockBindRecordService.SelectPO(wLoginUser, wParams,
                            wErrorCode);
                    if (sfcFrockBindRecord1 == null || sfcFrockBindRecord1.ID <= 0) {
                        return wResult;
                    }
                    //②查询芯子与产品的组装记录
                    wParams.clear();
                    wParams.put("SourceCode", sfcFrockBindRecord1.ComponentCode);
                    wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                    wParams.put("TargetComponentType", PDMComponentTypes.Product.getValue());
                    SFCAssemblyRecord sfcAssemblyRecord = mSFCAssemblyRecordService.SelectPO(wLoginUser, wParams,
                            wErrorCode);
                    if (sfcAssemblyRecord == null || sfcAssemblyRecord.ID <= 0) {
                        return wResult;
                    }
                    //根据成品编码获取成品工件记录
                    wParams.clear();
                    wParams.put("Code", sfcAssemblyRecord.TargetCode);
                    //③返回前端
                    wResult.Result = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                            wErrorCode);
                    if (wResult.Result.ID <= 0) {
                        wResult.Result.Code = sfcAssemblyRecord.TargetCode;
                    }
                }
            } else if (StringUtils.isNotEmpty(wMouldCode)) {
                //查询托盘码
                Map<String, Object> wParams = new HashMap<String, Object>();
                wParams.put("ComponentCode", wMouldCode);
                wParams.put("ComponentType", PDMComponentTypes.Mold.getValue());
                wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
                SFCFrockBindRecord sfcFrockBindRecord = mSFCFrockBindRecordService.SelectPO(wLoginUser, wParams,
                        wErrorCode);
                if (sfcFrockBindRecord == null || sfcFrockBindRecord.ID <= 0) {
                    return wResult;
                }
                //根据托盘码查询芯子码
                wParams.clear();
                wParams.put("FrockLedgerCode", sfcFrockBindRecord.FrockLedgerCode);
                wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
                SFCFrockBindRecord sfcFrockBindRecord1 = mSFCFrockBindRecordService.SelectPO(wLoginUser, wParams,
                        wErrorCode);
                if (sfcFrockBindRecord1 == null || sfcFrockBindRecord1.ID <= 0) {
                    return wResult;
                }
                //②查询芯子与产品的组装记录
                wParams.clear();
                wParams.put("SourceCode", sfcFrockBindRecord1.ComponentCode);
                wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                wParams.put("TargetComponentType", PDMComponentTypes.Product.getValue());
                SFCAssemblyRecord sfcAssemblyRecord = mSFCAssemblyRecordService.SelectPO(wLoginUser, wParams,
                        wErrorCode);
                if (sfcAssemblyRecord == null || sfcAssemblyRecord.ID <= 0) {
                    return wResult;
                }
                //根据成品编码获取成品工件记录
                wParams.clear();
                wParams.put("Code", sfcAssemblyRecord.TargetCode);
                //③返回前端
                wResult.Result = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                        wErrorCode);
                if (wResult.Result.ID <= 0) {
                    wResult.Result.Code = sfcAssemblyRecord.TargetCode;
                }
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_QueryProductInfoByTray", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCTaskStartCheck> SFC_QueryTaskStartCheckInfo(BMSEmployee wLoginUser, int wTaskSelfID) {
        ServiceResult<SFCTaskStartCheck> wResult = new ServiceResult<>();
        wResult.Result = new SFCTaskStartCheck();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //检查设备点检状态
            SFCServiceImpl.getInstance().CheckDevicePointCheck(wLoginUser, wTaskSelfID, wErrorCode);

            //①查询开工检查单
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("TaskSelfID", wTaskSelfID);
            wResult.Result = mSFCTaskStartCheckService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            //②查询物料是否填写完毕
            wParams.clear();
            wParams.put("ID", wTaskSelfID);
            SFCTaskSelf sfcTaskSelf = mSFCTaskSelfService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            //工序bom
            wParams.clear();
            wParams.put("RoutePartPointID", sfcTaskSelf.RoutePartPointID);
            wParams.put("Active", 1);
            List<MSSBOMItem> mssbomItems = mMSSBOMItemService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            if (mssbomItems.size() > 0) {
                //查询工位实时物料
                wParams.clear();
                wParams.put("StationID", sfcTaskSelf.StationID);
                wParams.put("RoutePartPointID", sfcTaskSelf.RoutePartPointID);
                List<SFCStationMaterial> sfcStationMaterials = mSFCStationMaterialService.SelectPOList(wLoginUser,
                        wParams, Pagination.getNewMaxSize(),
                        wErrorCode);
                if (mssbomItems.stream().anyMatch(p -> p.IsCodeScanning == 1
                        && sfcStationMaterials.stream().noneMatch(q -> q.MaterialID == p.MaterialID
                        && StringUtils.isNotEmpty(q.RawMaterialLot)))) {
                    wResult.Result.MaterialIsWrite = 0;
                } else {
                    if (mssbomItems.stream().anyMatch(p -> p.IsCodeScanning != 1 && p.IsCheck == 1
                            && sfcStationMaterials.stream().noneMatch(q -> q.MaterialID == p.MaterialID
                            && StringUtils.isNotEmpty(q.BatchNumber)))) {
                        wResult.Result.MaterialIsWrite = 0;
                    } else {
                        wResult.Result.MaterialIsWrite = 1;
                    }
                }
            } else {
                wResult.Result.MaterialIsWrite = 2;
            }

            if (wResult.Result.ID > 0) {
                //③查询工艺、环境参数是否填写完毕
                //参数填写记录
                wParams.clear();
                wParams.put("TaskStartCheckID", wResult.Result.ID);
                List<SFCTaskParamItem> sfcTaskParamItems = mSFCTaskParamItemService.SelectPOList(wLoginUser, wParams,
                        Pagination.getNewMaxSize(),
                        wErrorCode);
                //工艺参数、环境参数配置
                wParams.clear();
                wParams.put("RoutePartPointID", sfcTaskSelf.RoutePartPointID);
                wParams.put("Active", 1);
                List<FPCRoutePartPointParameter> fpcRoutePartPointParameters =
                        mFPCRoutePartPointParameterService.SelectPOList(wLoginUser, wParams, Pagination.getNewMaxSize(),
                                wErrorCode);
                //工艺参数
                List<FPCRoutePartPointParameter> wTechParamsList =
                        fpcRoutePartPointParameters.stream().filter(p -> p.ParamType == FPCParamType.PROCESS_PARAMETERS.getValue()).collect(Collectors.toList());
                if (wTechParamsList.size() > 0) {
                    if (wTechParamsList.stream().anyMatch(p -> sfcTaskParamItems.stream().noneMatch(q -> q.PartPointParamID == p.ID && StringUtils.isNotEmpty(q.ParamValue)))) {
                        wResult.Result.ProcessParametersIsWrite = 0;
                    } else {
                        wResult.Result.ProcessParametersIsWrite = 1;
                    }
                } else {
                    wResult.Result.ProcessParametersIsWrite = 2;
                }
                //环境参数
                List<FPCRoutePartPointParameter> wEnvironParamsList =
                        fpcRoutePartPointParameters.stream().filter(p -> p.ParamType == FPCParamType.ENVIRONMENT_PARAMETERS.getValue()).collect(Collectors.toList());
                if (wEnvironParamsList.size() > 0) {
                    if (wEnvironParamsList.stream().anyMatch(p -> sfcTaskParamItems.stream().noneMatch(q -> q.PartPointParamID == p.ID && StringUtils.isNotEmpty(q.ParamValue)))) {
                        wResult.Result.EnvironmentalParametersIsWrite = 0;
                    } else {
                        wResult.Result.EnvironmentalParametersIsWrite = 1;
                    }
                } else {
                    wResult.Result.EnvironmentalParametersIsWrite = 2;
                }
            }

            //设备点检状态更新
            SFCServiceImpl.getInstance().CheckDevicePointCheck(wLoginUser, wTaskSelfID, wErrorCode);

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCFrockBindRecord>> SFC_QueryFrockBindRecordAll(BMSEmployee wLoginUser, Map<String,
            Object> wParams, Pagination wPagination) {
        ServiceResult<List<SFCFrockBindRecord>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①条件查询记录
            wResult.Result = mSFCFrockBindRecordService.SelectPOList(wLoginUser, wParams, wPagination,
                    wErrorCode);
            //②翻译订单、产品信息
            if (wResult.Result.size() > 0) {
                for (SFCFrockBindRecord sfcFrockBindRecord : wResult.Result) {
                    wParams.clear();
                    wParams.put("CodeEQ", sfcFrockBindRecord.ComponentCode);
                    SFCWorkpieceRecord sfcWorkpieceRecord = mSFCWorkpieceRecordService.SelectPO(wLoginUser,
                            wParams,
                            wErrorCode);
                    if (sfcWorkpieceRecord != null && sfcWorkpieceRecord.ID > 0) {
                        sfcFrockBindRecord.OrderID = sfcWorkpieceRecord.OrderID;
                        sfcFrockBindRecord.OrderNo = sfcWorkpieceRecord.OrderNo;
                        sfcFrockBindRecord.ProductID = sfcWorkpieceRecord.ProductID;
                        sfcFrockBindRecord.ProductNo = sfcWorkpieceRecord.ProductNo;
                        sfcFrockBindRecord.ProductName = sfcWorkpieceRecord.ProductName;
                    }
                }
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_QueryFrockBindRecordAll", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> SFC_GetComponentTypeByBarCode(BMSEmployee wLoginUser, String wBarCode) {
        ServiceResult<String> wResult = new ServiceResult<>();
        wResult.Result = "";
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①托盘、模具
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("CodeEQ", wBarCode);
            DMSFrockLedger wDMSFrockLedger = mDMSFrockLedgerService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (wDMSFrockLedger != null && wDMSFrockLedger.ID > 0) {
                if (wDMSFrockLedger.FrockType == AMSFrockType.TP.getValue()) {
                    wResult.Result = PDMComponentTypes.Tray.getLabel();
                    return wResult;
                } else if (wDMSFrockLedger.FrockType == AMSFrockType.MJ.getValue()) {
                    wResult.Result = PDMComponentTypes.Mold.getLabel();
                    return wResult;
                }
            }
            //③工件记录
            wParams.clear();
            wParams.put("CodeEQ", wBarCode);
            SFCWorkpieceRecord sfcWorkpieceRecord = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (sfcWorkpieceRecord != null && sfcWorkpieceRecord.ID > 0) {
                wResult.Result = PDMComponentTypes.getEnumType(sfcWorkpieceRecord.ComponentType).getLabel();
                return wResult;
            }
            //④报错
            wResult.FaultCode += StringUtils.Format("无法识别出【{0}】的条码类型!", wBarCode);
            return wResult;
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_AutoAssembly(BMSEmployee wLoginUser, SFCTaskSelf wSFCTaskSelf, String wTrayCode,
                                                   OutResult<Integer> wErrorCode) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            //①根据托盘获取托盘绑定芯子记录
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("FrockLedgerCode", wTrayCode);
            wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
            wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
            List<SFCFrockBindRecord> sfcFrockBindRecordList = mSFCFrockBindRecordService.SelectPOList(wLoginUser,
                    wParams, Pagination.getNewMaxSize(),
                    wErrorCode);
            if (sfcFrockBindRecordList == null || sfcFrockBindRecordList.size() <= 0) {
                wResult.FaultCode += "芯子未与托盘绑定!";
                return wResult;
            }
            //②查询芯子组装记录，判断芯子是否与成品组装
            wParams.clear();
            wParams.put("SourceCode", sfcFrockBindRecordList.get(0).ComponentCode);
            wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
            wParams.put("TargetComponentType", PDMComponentTypes.Product.getValue());
            List<SFCAssemblyRecord> sfcAssemblyRecords = mSFCAssemblyRecordService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(), wErrorCode);
            if (sfcAssemblyRecords != null && sfcAssemblyRecords.size() > 0) {
                wResult.FaultCode += "芯子已与成品组装!";
                return wResult;
            }
            //③根据工单创建成品码
            BCMRuleCode wBCMRuleCode =
                    SFCServiceImpl.getInstance().SFC_CreateBarCodeByTask(wLoginUser, wSFCTaskSelf).Result;
            if (StringUtils.isEmpty(wBCMRuleCode.Code)) {
                wResult.FaultCode += "成品码创建失败!";
                return wResult;
            }
            //④调用组装接口，将芯子与成品组装
            String wSourceCodes = StringUtils.Join(",",
                    sfcFrockBindRecordList.stream().map(p -> p.ComponentCode).distinct().collect(Collectors.toList()));
            wResult = SFCServiceImpl.getInstance().SFC_WorkpieceAssembly(wLoginUser, wSourceCodes,
                    wBCMRuleCode.Code, wSFCTaskSelf, 0);
            if (StringUtils.isNotEmpty(wResult.FaultCode)) {
                return wResult;
            }
            //生成工件记录
            if (StringUtils.isEmpty(wResult.getFaultCode())) {
                SFCWorkpieceRecord wSFCWorkpieceRecord = new SFCWorkpieceRecord();
                wSFCWorkpieceRecord.setUserInfo(wLoginUser);
                wSFCWorkpieceRecord.Code = wBCMRuleCode.Code;
                wSFCWorkpieceRecord.ID = 0;
                wSFCWorkpieceRecord.OffLineStationID = 0;
                wSFCWorkpieceRecord.OffLineTime = CalendarTool.getBasicDate();
                wSFCWorkpieceRecord.OnLineStationID = wSFCTaskSelf.StationID;
                wSFCWorkpieceRecord.OnLineTime = Calendar.getInstance();
                wSFCWorkpieceRecord.OrderID = wSFCTaskSelf.OrderID;
                wSFCWorkpieceRecord.OrderNo = wSFCTaskSelf.OrderNo;
                wSFCWorkpieceRecord.ProductID = wSFCTaskSelf.ProductID;
                wSFCWorkpieceRecord.ComponentType = wSFCTaskSelf.ComponentType;
                wSFCWorkpieceRecord.Status = SFCTaskStatus.Todo.getValue();
                mSFCWorkpieceRecordService.UpdatePo(wLoginUser, wSFCWorkpieceRecord, wErrorCode);
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCTaskSelf>> SFC_QuerySFCTaskSelfAll(BMSEmployee wLoginUser,
                                                                    Map<String, Object> wParams,
                                                                    Pagination wPagination) {
        ServiceResult<List<SFCTaskSelf>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //设备查询
            if (wParams.containsKey("DeviceID")) {
                int deviceID = StringUtils.parseInt(wParams.get("DeviceID"));
                if (deviceID > 0) {
                    Map<String, Object> wParams1 = new HashMap<String, Object>();
                    wParams1.put("DeviceID", deviceID);
                    List<FMCStation> fmcStations = mFMCStationService.SelectPOList(wLoginUser, wParams1,
                            Pagination.getNewMaxSize(),
                            wErrorCode);
                    if (fmcStations != null && fmcStations.size() > 0) {
                        String wStationIDs = StringUtils.Join(",",
                                fmcStations.stream().map(p -> p.ID).distinct().collect(Collectors.toList()));
                        wParams.put("StationID", wStationIDs);
                    } else {
                        return wResult;
                    }
                }
            }

            wResult.Result = mSFCTaskSelfService.SelectPOList(wLoginUser, wParams, wPagination,
                    wErrorCode);

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_QuerySFCTaskSelfAll", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> SFC_ExportFactoryTest_V1(BMSEmployee wLoginUser, SFCFactoryTest wSFCFactoryTest) {
        ServiceResult<String> wResult = new ServiceResult<>();
        wResult.Result = "";
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①获取参数
            List<Integer> wSheetIndexList = SFC_GetSheetIndexList(wLoginUser, wSFCFactoryTest, wErrorCode);
            List<Integer> wToRemoveSheetIndexList = SFC_GetToRemoveSheetIndexList(wLoginUser, wSheetIndexList,
                    wErrorCode);
            Map<Integer, List<ExcelCellData>> wReplaceDataListMap = SFC_GetReplaceDataListMap(wLoginUser,
                    wSheetIndexList,
                    wSFCFactoryTest, wErrorCode);
            Map<Integer, List<Integer>> wToRemoveRowIndexListMap = SFC_GetToRemoveRowIndexListMap(wLoginUser,
                    wSheetIndexList,
                    wSFCFactoryTest, wErrorCode);
            Map<Integer, List<CellRangeAddress>> wRegionMap = SFC_GetRegionMap(wLoginUser, wSheetIndexList,
                    wSFCFactoryTest, wErrorCode);
            //③输出打印Excel
            String templatePath = StringUtils.Format("{0}FactoryTestTemplate1.xlsx", Constants.getConfigPath());

            String wFileName = StringUtils.Format("出厂试验单{0}.xlsx",
                    new SimpleDateFormat("yyyyMMddHHmmss").format(Calendar.getInstance().getTime()));

            String outputPath = SFC_GetOutputPath(wLoginUser, wFileName, wErrorCode);
            ExcelUtil.fillTemplate_V1(templatePath, outputPath, wSheetIndexList, wToRemoveSheetIndexList,
                    wReplaceDataListMap, wToRemoveRowIndexListMap, wRegionMap);

            wResult.Result = StringUtils.Format("/{0}/export/{1}",
                    Configuration.readConfigString("project.name", "application"), wFileName);

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_ExportFactoryTest", e);
        }
        return wResult;
    }

    /**
     * 获取合并单元格信息
     */
    private Map<Integer, List<CellRangeAddress>> SFC_GetRegionMap(BMSEmployee wLoginUser,
                                                                  List<Integer> wSheetIndexList,
                                                                  SFCFactoryTest wSFCFactoryTest,
                                                                  OutResult<Integer> wErrorCode) {
        Map<Integer, List<CellRangeAddress>> wResult = new HashMap<>();
        try {
            //①获取主端子数
            int wNumber = 4;
            if (wSFCFactoryTest.ItemList.stream().anyMatch(p -> p.ValueList != null
                    && p.ValueList.size() > 0
                    && p.ValueList.stream().anyMatch(q -> q.contains(",")))) {
                SFCFactoryTestItem sfcFactoryTestItem =
                        wSFCFactoryTest.ItemList.stream().filter(p -> p.ValueList != null
                                && p.ValueList.size() > 0
                                && p.ValueList.stream().anyMatch(q -> q.contains(","))).findFirst().get();
                String wValue = sfcFactoryTestItem.ValueList.stream().filter(p -> p.contains(",")).findFirst().get();
                wNumber = wValue.split(",").length;
                if (wNumber > 4) {
                    wNumber = 4;
                }
            } else {
                wNumber = 1;
            }

            if (wNumber == 1) {
                return wResult;
            }
            //11 11+3 11+3+3 11+3+3+3
            //③创建合并单元格信息
            List<CellRangeAddress> wList;
            CellRangeAddress wCellRangeAddress;
            for (int wSheetIndex : wSheetIndexList) {
                wList = new ArrayList<>();

                //①获取当前Sheet数据
                int wStartIndex = wSheetIndex * 4;
                int wEndIndex = wSheetIndex * 4 + 3;
                if (wEndIndex > wSFCFactoryTest.ItemList.size() - 1) {
                    wEndIndex = wSFCFactoryTest.ItemList.size() - 1;
                }
                List<SFCFactoryTestItem> sfcFactoryTestItems = wSFCFactoryTest.ItemList.subList(wStartIndex,
                        wEndIndex + 1);

                for (int i = 1; i <= 4; i++) {
                    //①序号
                    wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                            11 + i * wNumber - 1, 0, 0);
                    wList.add(wCellRangeAddress);
                    //②试验日期
                    wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                            11 + i * wNumber - 1, 1, 1);
                    wList.add(wCellRangeAddress);
                    //③电容编号
                    wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                            11 + i * wNumber - 1, 2, 2);
                    wList.add(wCellRangeAddress);
                    //④尺寸外观检查
                    wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                            11 + i * wNumber - 1, 4, 4);
                    wList.add(wCellRangeAddress);
                    //⑤重量
                    wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                            11 + i * wNumber - 1, 5, 5);
                    wList.add(wCellRangeAddress);
                    //⑥3KVDC (60s)
                    if (i - 1 <= sfcFactoryTestItems.size() - 1) {
                        if (sfcFactoryTestItems.get(i - 1).ValueList.get(2).contains(",")) {
                            List<String> wTempList =
                                    Arrays.stream(sfcFactoryTestItems.get(i - 1).ValueList.get(2).split(",")).collect(Collectors.toList());
                            if (wTempList.stream().allMatch(p -> p.equals(wTempList.get(0)))) {
                                wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                                        11 + i * wNumber - 1, 6, 6);
                                wList.add(wCellRangeAddress);
                            }
                        }
                    } else {
                        wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                                11 + i * wNumber - 1, 6, 6);
                        wList.add(wCellRangeAddress);
                    }
                    //⑦6KVAC (60s)
                    if (i - 1 <= sfcFactoryTestItems.size() - 1) {
                        if (sfcFactoryTestItems.get(i - 1).ValueList.get(4).contains(",")) {
                            List<String> wTempList =
                                    Arrays.stream(sfcFactoryTestItems.get(i - 1).ValueList.get(4).split(",")).collect(Collectors.toList());
                            if (wTempList.stream().allMatch(p -> p.equals(wTempList.get(0)))) {
                                wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                                        11 + i * wNumber - 1, 8, 8);
                                wList.add(wCellRangeAddress);
                            }
                        }
                    } else {
                        wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                                11 + i * wNumber - 1, 8, 8);
                        wList.add(wCellRangeAddress);
                    }
                    //⑧"漏电流 （mA）"
                    if (i - 1 <= sfcFactoryTestItems.size() - 1) {
                        if (sfcFactoryTestItems.get(i - 1).ValueList.get(5).contains(",")) {
                            List<String> wTempList =
                                    Arrays.stream(sfcFactoryTestItems.get(i - 1).ValueList.get(5).split(",")).collect(Collectors.toList());
                            if (wTempList.stream().allMatch(p -> p.equals(wTempList.get(0)))) {
                                wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                                        11 + i * wNumber - 1, 9, 9);
                                wList.add(wCellRangeAddress);
                            }
                        }
                    } else {
                        wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                                11 + i * wNumber - 1, 9, 9);
                        wList.add(wCellRangeAddress);
                    }
                    //⑨"绝缘电阻 ≥2000MΩ"
                    if (i - 1 <= sfcFactoryTestItems.size() - 1) {
                        if (sfcFactoryTestItems.get(i - 1).ValueList.get(9).contains(",")) {
                            List<String> wTempList =
                                    Arrays.stream(sfcFactoryTestItems.get(i - 1).ValueList.get(9).split(",")).collect(Collectors.toList());
                            if (wTempList.stream().allMatch(p -> p.equals(wTempList.get(0)))) {
                                wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                                        11 + i * wNumber - 1, 13, 13);
                                wList.add(wCellRangeAddress);
                            }
                        }
                    } else {
                        wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                                11 + i * wNumber - 1, 13, 13);
                        wList.add(wCellRangeAddress);
                    }
                    //⑩结论
                    wCellRangeAddress = new CellRangeAddress(11 + (i - 1) * wNumber,
                            11 + i * wNumber - 1, 17, 17);
                    wList.add(wCellRangeAddress);
                }
                wResult.put(wSheetIndex, wList);
            }
        } catch (Exception ex) {
            log.error("SFC_GetRegionMap", ex);
        }
        return wResult;
    }

    /**
     * 获取待替换的Sheet数据集合
     */
    private Map<Integer, List<ExcelCellData>> SFC_GetReplaceDataListMap(BMSEmployee wLoginUser,
                                                                        List<Integer> wSheetIndexList,
                                                                        SFCFactoryTest wSFCFactoryTest,
                                                                        OutResult<Integer> wErrorCode) {
        Map<Integer, List<ExcelCellData>> wResult = new HashMap<>();
        try {
            //②获取待替换的表头上信息
            List<ExcelCellData> wTableHeadList = GetTableHeadList(wLoginUser, wSFCFactoryTest, wErrorCode);
            //③获取待替换的表头工艺参数标准
            List<ExcelCellData> wTableParamList = GetTableParamList(wLoginUser, wSFCFactoryTest, wErrorCode);
            //获取系统参数
            Map<String, Object> wParams = new HashMap<String, Object>();
            List<BFCSystemConfig> bfcSystemConfigs = mBFCSystemConfigService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);

            List<ExcelCellData> wList;
            int wIndex = 0;
            ExcelCellData wExcelCellData;
            for (int wSheetIndex : wSheetIndexList) {
                wList = new ArrayList<>();
                wList.addAll(wTableHeadList);
                wList.addAll(wTableParamList);
                //①获取当前Sheet数据
                int wStartIndex = wSheetIndex * 4;
                int wEndIndex = wSheetIndex * 4 + 3;
                if (wEndIndex > wSFCFactoryTest.ItemList.size() - 1) {
                    wEndIndex = wSFCFactoryTest.ItemList.size() - 1;
                }
                List<SFCFactoryTestItem> sfcFactoryTestItems = wSFCFactoryTest.ItemList.subList(wStartIndex,
                        wEndIndex + 1);
                //④遍历当前Sheet数据，得到行ExcelCellData数据
                List<ExcelCellData> wExcelCellDataList = GetExcelCellDataRowList(wLoginUser, sfcFactoryTestItems,
                        wErrorCode);
                wList.addAll(wExcelCellDataList);
                //若为最后一页，且数量不满足要求，则需要添加待清除的数据
                if (wIndex == wSheetIndexList.size() - 1 && wSFCFactoryTest.ItemList.size() % 4 != 0) {
                    for (int i = sfcFactoryTestItems.size() + 1; i <= 4; i++) {
                        //序号 11 11+4 11+4+4 11+4+4+4
                        wExcelCellData = new ExcelCellData(11 + (i - 1) * 4, 0, "");
                        wList.add(wExcelCellData);
                        //主端子
                        for (int j = 1; j <= 4; j++) {
                            wExcelCellData = new ExcelCellData(11 + (i - 1) * 4 + j - 1, 3, "");
                            wList.add(wExcelCellData);
                        }
                    }
                }
                //添加待替换的参数范围
                List<ExcelCellData> wStandardList = GetStandardList(wLoginUser, wSFCFactoryTest, bfcSystemConfigs,
                        wErrorCode);
                if (wStandardList.size() > 0) {
                    wList.addAll(wStandardList);
                }
                //添加结果集
                wResult.put(wSheetIndex, wList);

                wIndex++;
            }
        } catch (Exception ex) {
            log.error("SFC_GetReplaceDataListMap", ex);
        }
        return wResult;
    }

    /**
     * 获取待替换的标准范围单元格数据
     */
    private List<ExcelCellData> GetStandardList(BMSEmployee wLoginUser, SFCFactoryTest wSFCFactoryTest,
                                                List<BFCSystemConfig> bfcSystemConfigs, OutResult<Integer> wErrorCode) {
        List<ExcelCellData> wResult = new ArrayList<>();
        try {
            if (wSFCFactoryTest.StandardMap == null || wSFCFactoryTest.StandardMap.size() <= 0) {
                return wResult;
            }

            Map<String, String> wNameValueMap =
                    bfcSystemConfigs.stream().collect(Collectors.toMap(BFCSystemConfig::getName
                            , BFCSystemConfig::getValue));

            Map<String, String> standardMap = wSFCFactoryTest.StandardMap;
            //①重量
            if (wNameValueMap.containsKey("FactoryTest_F10")) {
                String factoryTest_f10 = wNameValueMap.get("FactoryTest_F10");
                if (standardMap.containsKey(factoryTest_f10)) {
                    ExcelCellData wExcelCellData = new ExcelCellData(9, 5, standardMap.get(factoryTest_f10));
                    wResult.add(wExcelCellData);
                }
            }
            //②电容值
            if (wNameValueMap.containsKey("FactoryTest_K10")) {
                String factoryTest_f10 = wNameValueMap.get("FactoryTest_K10");
                if (standardMap.containsKey(factoryTest_f10)) {
                    ExcelCellData wExcelCellData = new ExcelCellData(9, 10, standardMap.get(factoryTest_f10));
                    wResult.add(wExcelCellData);
                }
            }
            //③损耗值
            if (wNameValueMap.containsKey("FactoryTest_L10")) {
                String factoryTest_f10 = wNameValueMap.get("FactoryTest_L10");
                if (standardMap.containsKey(factoryTest_f10)) {
                    ExcelCellData wExcelCellData = new ExcelCellData(9, 11, standardMap.get(factoryTest_f10));
                    wResult.add(wExcelCellData);
                }
            }
            //④ESR
            if (wNameValueMap.containsKey("FactoryTest_M7")) {
                String factoryTest_f10 = wNameValueMap.get("FactoryTest_M7");
                if (standardMap.containsKey(factoryTest_f10)) {
                    ExcelCellData wExcelCellData = new ExcelCellData(6, 12, standardMap.get(factoryTest_f10));
                    wResult.add(wExcelCellData);
                }
            }
            //⑤绝缘电阻
            if (wNameValueMap.containsKey("FactoryTest_N7")) {
                String factoryTest_f10 = wNameValueMap.get("FactoryTest_N7");
                if (standardMap.containsKey(factoryTest_f10)) {
                    ExcelCellData wExcelCellData = new ExcelCellData(6, 13, standardMap.get(factoryTest_f10));
                    wResult.add(wExcelCellData);
                }
            }
            //⑥特殊环境电容值
            if (wNameValueMap.containsKey("FactoryTest_O10")) {
                String factoryTest_f10 = wNameValueMap.get("FactoryTest_O10");
                if (standardMap.containsKey(factoryTest_f10)) {
                    ExcelCellData wExcelCellData = new ExcelCellData(9, 14, standardMap.get(factoryTest_f10));
                    wResult.add(wExcelCellData);
                }
            }
            //⑦特殊环境损耗值
            if (wNameValueMap.containsKey("FactoryTest_P10")) {
                String factoryTest_f10 = wNameValueMap.get("FactoryTest_P10");
                if (standardMap.containsKey(factoryTest_f10)) {
                    ExcelCellData wExcelCellData = new ExcelCellData(9, 15, standardMap.get(factoryTest_f10));
                    wResult.add(wExcelCellData);
                }
            }
            //⑧特殊环境ESR
            if (wNameValueMap.containsKey("FactoryTest_Q8")) {
                String factoryTest_f10 = wNameValueMap.get("FactoryTest_Q8");
                if (standardMap.containsKey(factoryTest_f10)) {
                    ExcelCellData wExcelCellData = new ExcelCellData(7, 16, standardMap.get(factoryTest_f10));
                    wResult.add(wExcelCellData);
                }
            }
            //⑨环境
            if (wNameValueMap.containsKey("FactoryTest_O7")) {
                String factoryTest_f10 = wNameValueMap.get("FactoryTest_O7");
                if (standardMap.containsKey(factoryTest_f10)) {
                    ExcelCellData wExcelCellData = new ExcelCellData(6, 14, standardMap.get(factoryTest_f10));
                    wResult.add(wExcelCellData);
                }
            }
        } catch (Exception e) {
            log.error("GetStandardList", e);
        }
        return wResult;
    }

    /**
     * 获取Sheet行数据替换集合
     */
    private List<ExcelCellData> GetExcelCellDataRowList(BMSEmployee wLoginUser,
                                                        List<SFCFactoryTestItem> sfcFactoryTestItems,
                                                        OutResult<Integer> wErrorCode) {
        List<ExcelCellData> wResult = new ArrayList<>();
        try {
            ExcelCellData wExcelCellData;
            SFCFactoryTestItem sfcFactoryTestItem;

            for (int i = 0; i < sfcFactoryTestItems.size(); i++) {
                sfcFactoryTestItem = sfcFactoryTestItems.get(i);
                //②试验日期
                wExcelCellData = new ExcelCellData(4 * i + 11, 1,
                        StringUtils.parseCalendarToString(sfcFactoryTestItem.TestDate, "yyyy/MM/dd"));
                wResult.add(wExcelCellData);
                //③电容编号
                wExcelCellData = new ExcelCellData(4 * i + 11, 2, sfcFactoryTestItem.CapacitorNumber);
                wResult.add(wExcelCellData);
                //④尺寸外观检查...
                int wIndex = 4;

                //处理相同数据的合并
//                List<String> wValueList = new ArrayList<>();
//                for (String wValue : sfcFactoryTestItem.ValueList) {
//                    if (wValue.contains(",")) {
//                        List<String> wList = Arrays.stream(wValue.split(",")).collect(Collectors.toList());
//                        if (wList.stream().allMatch(p -> p.equals(wList.get(0)))) {
//                            wValueList.add(wList.get(0));
//                        } else {
//                            wValueList.add(wValue);
//                        }
//                    } else {
//                        wValueList.add(wValue);
//                    }
//                }
//                sfcFactoryTestItem.ValueList = wValueList;
                for (String wValue : sfcFactoryTestItem.ValueList) {
                    if (wValue.contains(",")) {
                        String[] split = wValue.split(",");

                        for (int j = 0; j < split.length; j++) {
                            if (j >= 4) {
                                break;
                            }

                            wExcelCellData = new ExcelCellData(4 * i + 11 + j, wIndex, split[j]);
                            wResult.add(wExcelCellData);
                        }

                    } else {
                        wExcelCellData = new ExcelCellData(4 * i + 11, wIndex, wValue);
                        wResult.add(wExcelCellData);
                    }
                    wIndex++;
                }
                //⑤结论
                wExcelCellData = new ExcelCellData(4 * i + 11, 17, sfcFactoryTestItem.CheckResult);
                wResult.add(wExcelCellData);
            }
        } catch (Exception ex) {
            log.error("GetExcelCellDataRowList", ex);
        }
        return wResult;
    }

    /**
     * 获取待替换的工艺参数标准 todo
     */
    private List<ExcelCellData> GetTableParamList(BMSEmployee wLoginUser, SFCFactoryTest wSFCFactoryTest,
                                                  OutResult<Integer> wErrorCode) {
        List<ExcelCellData> wResult = new ArrayList<>();
        try {

        } catch (Exception ex) {
            log.error("GetTableParamList", ex);
        }
        return wResult;
    }

    /**
     * 获取表头上的替换信息
     */
    private List<ExcelCellData> GetTableHeadList(BMSEmployee wLoginUser, SFCFactoryTest wSFCFactoryTest,
                                                 OutResult<Integer> wErrorCode) {
        List<ExcelCellData> wResult = new ArrayList<>();
        try {
            //表码
            ExcelCellData wExcelCellData = new ExcelCellData(3, 0, StringUtils.Format("表码：{0}",
                    wSFCFactoryTest.TableCode));
            wResult.add(wExcelCellData);
            //报告编号
            wExcelCellData = new ExcelCellData(3, 14, StringUtils.Format("报告编号：{0}",
                    wSFCFactoryTest.ReportNumber));
            wResult.add(wExcelCellData);
            //产品名称
            wExcelCellData = new ExcelCellData(4, 0, StringUtils.Format("产品名称：{0}",
                    wSFCFactoryTest.ProductName));
            wResult.add(wExcelCellData);
            //试区温度、湿度
            wExcelCellData = new ExcelCellData(4, 14, StringUtils.Format("试区温度：{0}℃   湿度：{1}％",
                    String.valueOf(wSFCFactoryTest.Temperature).replaceAll("[.0]+$", ""),
                    String.valueOf(wSFCFactoryTest.Humidity).replaceAll("[.0]+$", "")));
            wResult.add(wExcelCellData);
            //产品型号
            wExcelCellData = new ExcelCellData(5, 0, StringUtils.Format("产品型号：{0}",
                    wSFCFactoryTest.ProductNo));
            wResult.add(wExcelCellData);
            //出厂日期
            SimpleDateFormat wSDF = new SimpleDateFormat("yyyy 年 MM 月 dd 日");
            String wCurrentTime = wSDF.format(wSFCFactoryTest.ProductDate.getTime());
            wExcelCellData = new ExcelCellData(5, 14, StringUtils.Format("出厂日期：{0}",
                    wCurrentTime));
            wResult.add(wExcelCellData);
        } catch (Exception ex) {
            log.error("GetTableHeadList", ex);
        }
        return wResult;
    }

    /**
     * 获取待删除的行下标集合
     */
    private Map<Integer, List<Integer>> SFC_GetToRemoveRowIndexListMap(BMSEmployee wLoginUser,
                                                                       List<Integer> wSheetIndexList,
                                                                       SFCFactoryTest wSFCFactoryTest,
                                                                       OutResult<Integer> wErrorCode) {
        Map<Integer, List<Integer>> wResult = new HashMap<>();
        try {
            Optional<SFCFactoryTestItem> first =
                    wSFCFactoryTest.ItemList.stream().filter(p -> p.ValueList != null && p.ValueList.size() > 0
                            && p.ValueList.stream().anyMatch(q -> q.contains(","))).findFirst();

            for (int wSheetIndex : wSheetIndexList) {
                List<Integer> wList = new ArrayList<>();
                if (first.isPresent()) {
                    SFCFactoryTestItem sfcFactoryTestItem = first.get();
                    String wValue =
                            sfcFactoryTestItem.ValueList.stream().filter(p -> p.contains(",")).findFirst().get();
                    String[] wValueS = wValue.split(",");
                    if (wValueS.length >= 4) {
                        return wResult;
                    }

                    for (int i = 3; i <= 6; i++) {
                        for (int j = i * 4 + wValueS.length - 1; j < i * 4 + 3; j++) {
                            wList.add(j);
                        }
                    }
                } else {
                    //只有一个主端子，其余行全部删除
                    for (int i = 3; i <= 6; i++) {
                        for (int j = i * 4; j < i * 4 + 3; j++) {
                            wList.add(j);
                        }
                    }
                }
                // 逆序排序
                wList.sort(Comparator.comparing(p -> p, Comparator.reverseOrder()));
                wResult.put(wSheetIndex, wList);
            }
        } catch (Exception ex) {
            log.error("SFC_GetToRemoveRowIndexListMap", ex);
        }
        return wResult;
    }

    /**
     * 获取待删除的Sheet下标集合
     */
    private List<Integer> SFC_GetToRemoveSheetIndexList(BMSEmployee wLoginUser, List<Integer> wSheetIndexList,
                                                        OutResult<Integer> wErrorCode) {
        List<Integer> wResult = new ArrayList<>();
        try {
            if (wSheetIndexList.size() == 0) {
                for (int i = 0; i < 5; i++) {
                    wResult.add(i);
                }
            } else {
                int wMaxIndex = wSheetIndexList.stream().max(Comparator.comparing(p -> p)).get();
                for (int i = wMaxIndex + 1; i < 5; i++) {
                    wResult.add(i);
                }
            }
        } catch (Exception e) {
            log.error("SFC_GetToRemoveSheetIndexList", e);
        }
        return wResult;

    }

    /**
     * 获取存在的Sheet下标集合
     */
    private List<Integer> SFC_GetSheetIndexList(BMSEmployee wLoginUser, SFCFactoryTest wSFCFactoryTest,
                                                OutResult<Integer> wErrorCode) {
        List<Integer> wResult = new ArrayList<>();
        try {
            if (wSFCFactoryTest.ItemList == null || wSFCFactoryTest.ItemList.size() <= 0) {
                return wResult;
            }

            int wSheetNum = 0;
            if (wSFCFactoryTest.ItemList.size() % 4 == 0) {
                wSheetNum = wSFCFactoryTest.ItemList.size() / 4;
            } else {
                wSheetNum = wSFCFactoryTest.ItemList.size() / 4 + 1;
            }
            for (int i = 0; i < wSheetNum; i++) {
                wResult.add(i);
            }
        } catch (Exception ex) {
            log.error("SFC_GetSheetIndexList", ex);
        }
        return wResult;
    }

    /**
     * 获取导出文件的路径
     */
    private String SFC_GetOutputPath(BMSEmployee wLoginUser, String wFileName, OutResult<Integer> wErrorCode) {
        String wResult = "";
        try {
            String wExportFolder = StringUtils.Format("{0}export/", Constants.getStaticPath());

            Path folder = Paths.get(wExportFolder);

            if (!Files.exists(folder)) {
                Files.createDirectories(folder);
            }

            wResult = StringUtils.Format("{0}{1}", wExportFolder, wFileName);
        } catch (Exception ex) {
            log.error("SFC_GetOutputPath", ex);
        }
        return wResult;
    }

    @Override
    public ServiceResult<String> SFC_GetProductCodeByBarCode(BMSEmployee wLoginUser, String wSourceCodes) {
        ServiceResult<String> wResult = new ServiceResult<>();
        wResult.Result = "";
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (StringUtils.isEmpty(wSourceCodes)) {
                return wResult;
            }
            //①托盘
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("CodeEQ", wSourceCodes);
            DMSFrockLedger wDMSFrockLedger = mDMSFrockLedgerService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (wDMSFrockLedger != null && wDMSFrockLedger.ID > 0 && wDMSFrockLedger.FrockType == AMSFrockType.TP.getValue()) {
                wParams.clear();
                wParams.put("FrockLedgerCode", wSourceCodes);
                wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
                wParams.put("ComponentType", "3,5,11");
                SFCFrockBindRecord sfcFrockBindRecord = mSFCFrockBindRecordService.SelectPO(wLoginUser,
                        wParams,
                        wErrorCode);
                if (sfcFrockBindRecord != null && sfcFrockBindRecord.ID > 0) {
                    //托盘绑定芯子，查组装记录
                    if (sfcFrockBindRecord.ComponentType == PDMComponentTypes.Core.getValue()) {
                        wParams.clear();
                        wParams.put("SourceCode", sfcFrockBindRecord.ComponentCode);
                        wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                        wParams.put("TargetComponentType", PDMComponentTypes.Product.getValue());
                        SFCAssemblyRecord sfcAssemblyRecord = mSFCAssemblyRecordService.SelectPO(wLoginUser, wParams,
                                wErrorCode);
                        if (sfcAssemblyRecord != null && sfcAssemblyRecord.ID > 0) {
                            wResult.Result = sfcAssemblyRecord.TargetCode;
                            return wResult;
                        }
                    } else if (sfcFrockBindRecord.ComponentType == PDMComponentTypes.Product.getValue()) {//托盘绑定成品，直接返回
                        wResult.Result = sfcFrockBindRecord.ComponentCode;
                        return wResult;
                    } else if (sfcFrockBindRecord.ComponentType == PDMComponentTypes.Mold.getValue()) {
                        //成品绑定模具，查芯子→查组装记录
                        wParams.clear();
                        wParams.put("ComponentCode", sfcFrockBindRecord.ComponentCode);
                        wParams.put("ComponentType", PDMComponentTypes.Mold.getValue());
                        wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
                        SFCFrockBindRecord sfcFrockBindRecord1 = mSFCFrockBindRecordService.SelectPO(wLoginUser,
                                wParams,
                                wErrorCode);
                        if (sfcFrockBindRecord1 != null && sfcFrockBindRecord1.ID > 0) {
                            wParams.clear();
                            wParams.put("FrockLedgerCode", sfcFrockBindRecord1.FrockLedgerCode);
                            wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                            wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
                            SFCFrockBindRecord sfcFrockBindRecord2 = mSFCFrockBindRecordService.SelectPO(wLoginUser,
                                    wParams,
                                    wErrorCode);
                            if (sfcFrockBindRecord2 != null && sfcFrockBindRecord2.ID > 0) {
                                wParams.clear();
                                wParams.put("SourceCode", sfcFrockBindRecord2.ComponentCode);
                                wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                                wParams.put("TargetComponentType", PDMComponentTypes.Product.getValue());
                                SFCAssemblyRecord sfcAssemblyRecord = mSFCAssemblyRecordService.SelectPO(wLoginUser,
                                        wParams,
                                        wErrorCode);
                                if (sfcAssemblyRecord != null && sfcAssemblyRecord.ID > 0) {
                                    wResult.Result = sfcAssemblyRecord.TargetCode;
                                    return wResult;
                                }
                            }
                        }
                    }
                }
            }
            //②模具
            else if (wDMSFrockLedger != null && wDMSFrockLedger.ID > 0 && wDMSFrockLedger.FrockType == AMSFrockType.MJ.getValue()) {
                wParams.clear();
                wParams.put("ComponentCode", wSourceCodes);
                wParams.put("ComponentType", PDMComponentTypes.Mold.getValue());
                wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
                SFCFrockBindRecord sfcFrockBindRecord1 = mSFCFrockBindRecordService.SelectPO(wLoginUser,
                        wParams,
                        wErrorCode);
                if (sfcFrockBindRecord1 != null && sfcFrockBindRecord1.ID > 0) {
                    wParams.clear();
                    wParams.put("FrockLedgerCode", sfcFrockBindRecord1.FrockLedgerCode);
                    wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                    wParams.put("Status", SFCFrockBindRecordStatus.BINDING.getValue());
                    SFCFrockBindRecord sfcFrockBindRecord2 = mSFCFrockBindRecordService.SelectPO(wLoginUser,
                            wParams,
                            wErrorCode);
                    if (sfcFrockBindRecord2 != null && sfcFrockBindRecord2.ID > 0) {
                        wParams.clear();
                        wParams.put("SourceCode", sfcFrockBindRecord2.ComponentCode);
                        wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                        wParams.put("TargetComponentType", PDMComponentTypes.Product.getValue());
                        SFCAssemblyRecord sfcAssemblyRecord = mSFCAssemblyRecordService.SelectPO(wLoginUser,
                                wParams,
                                wErrorCode);
                        if (sfcAssemblyRecord != null && sfcAssemblyRecord.ID > 0) {
                            wResult.Result = sfcAssemblyRecord.TargetCode;
                            return wResult;
                        }
                    }
                }
            }
            //③芯子
            wParams.clear();
            wParams.put("CodeEQ", wSourceCodes);
            SFCWorkpieceRecord sfcWorkpieceRecord = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (sfcWorkpieceRecord != null && sfcWorkpieceRecord.ID > 0 && sfcWorkpieceRecord.ComponentType == PDMComponentTypes.Core.getValue()) {
                wParams.clear();
                wParams.put("SourceCode", wSourceCodes);
                wParams.put("ComponentType", PDMComponentTypes.Core.getValue());
                wParams.put("TargetComponentType", PDMComponentTypes.Product.getValue());
                SFCAssemblyRecord sfcAssemblyRecord = mSFCAssemblyRecordService.SelectPO(wLoginUser, wParams,
                        wErrorCode);
                if (sfcAssemblyRecord != null && sfcAssemblyRecord.ID > 0) {
                    wResult.Result = sfcAssemblyRecord.TargetCode;
                    return wResult;
                }
            }
            //④成品
            else if (sfcWorkpieceRecord != null && sfcWorkpieceRecord.ID > 0 && sfcWorkpieceRecord.ComponentType == PDMComponentTypes.Product.getValue()) {
                wResult.Result = wSourceCodes;
                return wResult;
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateDayPlanFirstCheckStatus(BMSEmployee wLoginUser, SFCTaskSelf wSFCTaskSelf,
                                                                    FPCRoutePartPoint wFPCRoutePartPoint) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

//            if (wFPCRoutePartPoint.ReportMode == SFCTaskReportMode.NUMBER_REPORT.getValue()) {
//                return wResult;
//            }

            //①查询工步，判断是否需要首检
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("RoutePartPointID", wFPCRoutePartPoint.ID);
            wParams.put("IsFirstCheck", 1);
            wParams.put("Active", 1);
            List<FPCRouteStep> fpcRouteSteps = mFPCRouteStepService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            if (fpcRouteSteps == null || fpcRouteSteps.size() <= 0) {
                return wResult;
            }
            //②若需要，查询日计划
            wParams.clear();
            wParams.put("ID", wSFCTaskSelf.TaskPartPointDayID);
            APSTaskPartPointDay apsTaskPartPointDay = mAPSTaskPartPointDayService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            //③将日计划首检状态更新为`卡控中`
            if (apsTaskPartPointDay != null && apsTaskPartPointDay.ID > 0) {
                apsTaskPartPointDay.FirstCheckStatus = APSFirstCheckStatus.Locked.getValue();
                //④更新日计划
                mAPSTaskPartPointDayService.UpdatePo(wLoginUser, apsTaskPartPointDay, wErrorCode);
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_SubmitDayPlanFirstCheckStatus(BMSEmployee wLoginUser,
                                                                    List<SFCTaskIPT> wSFCTaskIPTs) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wSFCTaskIPTs = wSFCTaskIPTs.stream().filter(p -> p.FirstFlag == 1).collect(Collectors.toList());
            if (wSFCTaskIPTs.size() <= 0) {
                log.info("无首检单，无需更新首检状态");
                return wResult;
            }

            //查询是否还有未提交的首检单
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("OrderID", wSFCTaskIPTs.get(0).OrderID);
            wParams.put("RoutePartPointID", wSFCTaskIPTs.get(0).RoutePartPointID);
            wParams.put("Type", FPCCheckType.SELF_CHECK.getValue());
            wParams.put("FirstFlag", 1);
            wParams.put("Status", SFCTaskStatus.Default.getValue());
            List<SFCTaskIPT> sfcTaskIPTS = mSFCTaskIPTService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            if (sfcTaskIPTS.size() > 0) {
                log.info("有首检单未提交，无需更新首检状态");
                return wResult;
            }

            //①查询日计划
            wParams.clear();
            wParams.put("ID", wSFCTaskIPTs.get(0).TaskPartPointDayID);
            APSTaskPartPointDay apsTaskPartPointDay = mAPSTaskPartPointDayService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (apsTaskPartPointDay == null || apsTaskPartPointDay.ID <= 0) {
                log.error("日计划查询失败：ID=" + wSFCTaskIPTs.get(0).TaskPartPointDayID);
                return wResult;
            }


            //③更新首检状态
            if (wSFCTaskIPTs.stream().anyMatch(p -> p.Result != 1)) {
                if (apsTaskPartPointDay.FirstCheckStatus != APSFirstCheckStatus.Default.getValue()) {
                    apsTaskPartPointDay.FirstCheckStatus = APSFirstCheckStatus.CheckBad.getValue();
                }
            } else {
                if (apsTaskPartPointDay.FirstCheckStatus != APSFirstCheckStatus.Default.getValue()) {
                    apsTaskPartPointDay.FirstCheckStatus = APSFirstCheckStatus.CheckGood.getValue();
                }
            }
            mAPSTaskPartPointDayService.UpdatePo(wLoginUser, apsTaskPartPointDay, wErrorCode);

            //同步历史工单的首检状态
            List<Integer> wTaskSelfIDList =
                    wSFCTaskIPTs.stream().map(p -> p.TaskSelfID).distinct().collect(Collectors.toList());
            wParams.clear();
            List<SFCTaskSelf> sfcTaskSelves = mSFCTaskSelfService.SelectPOList(wLoginUser, wTaskSelfIDList, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            List<Integer> wHisTaskPartPointDayIDList =
                    sfcTaskSelves.stream().map(p -> p.TaskPartPointDayID).distinct().collect(Collectors.toList());
            wHisTaskPartPointDayIDList =
                    wHisTaskPartPointDayIDList.stream().filter(p -> p != apsTaskPartPointDay.ID).collect(Collectors.toList());
            if (wHisTaskPartPointDayIDList.size() > 0) {
                wParams.clear();
                List<APSTaskPartPointDay> apsTaskPartPointDays = mAPSTaskPartPointDayService.SelectPOList(wLoginUser,
                        wHisTaskPartPointDayIDList, wParams, Pagination.getNewMaxSize(),
                        wErrorCode);
                for (APSTaskPartPointDay taskPartPointDay : apsTaskPartPointDays) {
                    if (apsTaskPartPointDay.FirstCheckStatus != APSFirstCheckStatus.Default.getValue()) {
                        taskPartPointDay.FirstCheckStatus = apsTaskPartPointDay.FirstCheckStatus;
                    }
                    mAPSTaskPartPointDayService.UpdatePo(wLoginUser, taskPartPointDay, wErrorCode);
                }
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCWorkpieceRecord>> SFC_QueryComWorkpieceRecordList(BMSEmployee wLoginUser,
                                                                                   SFCWorkpieceRecord wSFCWorkpieceRecord) {
        ServiceResult<List<SFCWorkpieceRecord>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //元件
            if (wSFCWorkpieceRecord.ComponentType == PDMComponentTypes.Component.getValue()) {
                return wResult;
            }
            //芯子（元件）
            if (wSFCWorkpieceRecord.ComponentType == PDMComponentTypes.Core.getValue()) {
                Map<String, Object> wParams = new HashMap<String, Object>();
                wParams.put("CaseNo", wSFCWorkpieceRecord.Code);
                wResult.Result = mSFCWorkpieceRecordService.SelectPOList(wLoginUser, wParams,
                        Pagination.getNewMaxSize(),
                        wErrorCode);
                return wResult;
            }
            //成品（元件、芯子）
            if (wSFCWorkpieceRecord.ComponentType == PDMComponentTypes.Product.getValue()) {
                Map<String, Object> wParams = new HashMap<String, Object>();
                wParams.put("PackageNo", wSFCWorkpieceRecord.Code);
                wResult.Result = mSFCWorkpieceRecordService.SelectPOList(wLoginUser, wParams,
                        Pagination.getNewMaxSize(),
                        wErrorCode);
                return wResult;
            }
            //箱体（元件、芯子、成品）
            if (wSFCWorkpieceRecord.ComponentType == PDMComponentTypes.Box.getValue()) {
                Map<String, Object> wParams = new HashMap<String, Object>();
                wParams.put("BoxNo", wSFCWorkpieceRecord.Code);
                wResult.Result = mSFCWorkpieceRecordService.SelectPOList(wLoginUser, wParams,
                        Pagination.getNewMaxSize(),
                        wErrorCode);
                return wResult;
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_QueryComWorkpieceRecordList", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateStationMaterialList(BMSEmployee wLoginUser,
                                                                List<SFCStationMaterial> wSFCStationMaterialList,
                                                                SFCTaskSelf wSFCTaskSelf) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            mSFCStationMaterialService.UpdatePoList(wLoginUser, wSFCStationMaterialList, wErrorCode);
            //若为工单换料，需要触发首检
            if (wSFCTaskSelf != null && wSFCTaskSelf.ID > 0) {
                Map<String, Object> wParams = new HashMap<String, Object>();
                wParams.put("ID", wSFCTaskSelf.TaskPartPointDayID);
                APSTaskPartPointDay apsTaskPartPointDay = mAPSTaskPartPointDayService.SelectPO(wLoginUser, wParams,
                        wErrorCode);
                if (apsTaskPartPointDay.FirstCheckStatus != APSFirstCheckStatus.Default.getValue()) {
                    apsTaskPartPointDay.FirstCheckStatus = APSFirstCheckStatus.ToCheck.getValue();
                    mAPSTaskPartPointDayService.UpdatePo(wLoginUser, apsTaskPartPointDay, wErrorCode);
                }
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCTaskIPT> SFC_CreateSpotCheckTaskByWorkpieceNoAndTask(BMSEmployee wLoginUser,
                                                                                 String wWorkpieceNo,
                                                                                 SFCTaskSelf wSFCTaskSelf) {
        ServiceResult<SFCTaskIPT> wResult = new ServiceResult<>();
        wResult.Result = new SFCTaskIPT();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①根据工件号判断是否已经存在自检单,若存在，查询检验值，返回给前端
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("ComponentCode", wWorkpieceNo);
            wParams.put("OrderID", wSFCTaskSelf.OrderID);
            wParams.put("RoutePartPointID", wSFCTaskSelf.RoutePartPointID);
            wParams.put("Type", FPCCheckType.SELF_CHECK.getValue());
            SFCTaskIPT sfcTaskIPT = mSFCTaskIPTService.SelectPO(wLoginUser, wParams,
                    wErrorCode);

            List<IPTValue> wValueList = new ArrayList<>();

            if (sfcTaskIPT != null && sfcTaskIPT.ID > 0) {
                wResult.Result = sfcTaskIPT;
                if (wSFCTaskSelf.FirstCheckStatus != APSFirstCheckStatus.Default.getValue()) {
                    wResult.Result.FirstFlag = 1;
                }
                wResult.Result.TaskSelfID = wSFCTaskSelf.ID;
                wResult.Result.TaskPartPointDayID = wSFCTaskSelf.TaskPartPointDayID;
                wResult.Result.SamplingFlag = 1;
                mSFCTaskIPTService.UpdatePo(wLoginUser, wResult.Result, wErrorCode);

                //查询检验值
                wParams.clear();
                wParams.put("TaskID", sfcTaskIPT.ID);
                wValueList = mIPTValueService.SelectPOList(wLoginUser, wParams, Pagination.getNewMaxSize(),
                        wErrorCode);
                wResult.CustomResult.put("ValueList", wValueList);
                return wResult;
            }
            //③若不存在，调用创建接口，创建自检单，返回给前端
            wResult = SFCServiceImpl.getInstance().SFC_CreateTaskByWorkpieceNoAndTask(wLoginUser,
                    wSFCTaskSelf.StationID
                    , FPCCheckType.SELF_CHECK.getValue(), wWorkpieceNo, wSFCTaskSelf);
            if (wResult.Result.ID > 0 && StringUtils.isNotEmpty(wResult.Result.ComponentCode)) {
                if (wSFCTaskSelf.FirstCheckStatus != APSFirstCheckStatus.Default.getValue()) {
                    wResult.Result.FirstFlag = 1;
                }
                wResult.Result.SamplingFlag = 1;
                mSFCTaskIPTService.UpdatePo(wLoginUser, wResult.Result, wErrorCode);
            }

//            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCTaskParamItem>> SFC_ChangeParamList(BMSEmployee wLoginUser,
                                                                     List<DMSProcessRecord> wDMSProcessRecordList,
                                                                     List<DMSDeviceParameter> wDMSDeviceParameterList) {
        ServiceResult<List<SFCTaskParamItem>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            if (wDMSProcessRecordList == null || wDMSProcessRecordList.size() <= 0) {
                return wResult;
            }

            //提取设备ID集合
            List<Integer> wDeviceIDList =
                    wDMSProcessRecordList.stream().map(p -> p.DeviceID).distinct().collect(Collectors.toList());
            //根据设备ID集合获取设备台账
            Map<String, Object> wParams = new HashMap<String, Object>();
            List<DMSDeviceLedger> dmsDeviceLedgers = mDMSDeviceLedgerService.SelectPOList(wLoginUser, wDeviceIDList,
                    wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);

            List<DMSDeviceParameter> wParamList;
            SFCTaskParamItem wSFCTaskParamItem;
            for (DMSProcessRecord dmsProcessRecord : wDMSProcessRecordList) {
                wParamList =
                        wDMSDeviceParameterList.stream().filter(p -> p.DeviceID == dmsProcessRecord.DeviceID).collect(Collectors.toList());
                for (DMSDeviceParameter dmsDeviceParameter : wParamList) {
                    wSFCTaskParamItem = new SFCTaskParamItem();
                    //①参数编号
                    wSFCTaskParamItem.ParamCode = dmsDeviceParameter.Code;
                    //②参数名称
                    wSFCTaskParamItem.ParamName = dmsDeviceParameter.Name;
                    //③参数代码
                    wSFCTaskParamItem.VariableName = dmsDeviceParameter.VariableName;
                    //④参数值
                    wSFCTaskParamItem.ParamValue = "";
                    if (dmsProcessRecord.TechnologyParams != null && dmsProcessRecord.TechnologyParams.containsKey(dmsDeviceParameter.VariableName)) {
                        wSFCTaskParamItem.ParamValue =
                                StringUtils.parseString(dmsProcessRecord.TechnologyParams.get(dmsDeviceParameter.VariableName));
                    } else {
                        continue;
                    }
                    //⑤单位
                    wSFCTaskParamItem.UnitName = dmsDeviceParameter.AuxiliaryChar;
                    wSFCTaskParamItem.UnitCode = dmsDeviceParameter.AuxiliaryChar;
                    //⑥设备
                    Optional<DMSDeviceLedger> first =
                            dmsDeviceLedgers.stream().filter(p -> p.ID == dmsDeviceParameter.DeviceID).findFirst();
                    if (first.isPresent()) {
                        DMSDeviceLedger dmsDeviceLedger = first.get();
                        wSFCTaskParamItem.DeviceName = dmsDeviceLedger.Name;
                        wSFCTaskParamItem.DeviceCode = dmsDeviceLedger.Code;
                    }
                    wResult.Result.add(wSFCTaskParamItem);
                }
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_ChangeParamList", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_ReplacementJobCode(BMSEmployee wLoginUser, int wSFCAssemblyRecordID,
                                                         String wNewJobCode) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①验证组装记录是否存在
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("ID", wSFCAssemblyRecordID);
            SFCAssemblyRecord sfcAssemblyRecord = mSFCAssemblyRecordService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (sfcAssemblyRecord == null || sfcAssemblyRecord.ID <= 0) {
                wResult.FaultCode += "组装记录不存在，请检查AssemblyRecordID参数是否正确!";
                return wResult;
            }
            //②验证新工件记录是否存在
            wParams.clear();
            wParams.put("CodeEQ", wNewJobCode);
            SFCWorkpieceRecord sfcWorkpieceRecord = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (sfcWorkpieceRecord == null || sfcWorkpieceRecord.ID <= 0) {
                wResult.FaultCode += StringUtils.Format("新工件【{0}】为录入系统，请先自检!", wNewJobCode);
                return wResult;
            }
            //③验证组装记录的来源类型是否和工件记录的来源类型一致
            if (sfcAssemblyRecord.ComponentType != sfcWorkpieceRecord.ComponentType) {
                wResult.FaultCode += StringUtils.Format("组装记录来源类型【{0}】与工件记录来源类型【{1}】不一致，请检查!",
                        PDMComponentTypes.getEnumType(sfcAssemblyRecord.ComponentType).getLabel(),
                        PDMComponentTypes.getEnumType(sfcWorkpieceRecord.ComponentType).getLabel());
                return wResult;
            }
            //④验证新工件是否已组装
            wParams.clear();
            wParams.put("SourceCode", wNewJobCode);
            List<SFCAssemblyRecord> sfcAssemblyRecords = mSFCAssemblyRecordService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            if (sfcAssemblyRecords != null && sfcAssemblyRecords.size() > 0) {
                wResult.FaultCode += StringUtils.Format("新工件【{0}】已组装，请检查!", wNewJobCode);
                return wResult;
            }
            //⑤查询历史工件记录
            wParams.clear();
            wParams.put("CodeEQ", sfcAssemblyRecord.SourceCode);
            SFCWorkpieceRecord sfcWorkpieceRecord2 = mSFCWorkpieceRecordService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (sfcWorkpieceRecord2 == null || sfcWorkpieceRecord2.ID <= 0) {
                wResult.FaultCode += StringUtils.Format("原工件【{0}】记录不存在，请检查!", sfcAssemblyRecord.SourceCode);
                return wResult;
            }
            //⑥若为元件，则更新新工件的芯子码、成品码、箱条码、出厂条码，参考历史工件信息
            if (sfcAssemblyRecord.ComponentType == PDMComponentTypes.Component.getValue()) {
                sfcWorkpieceRecord.CaseNo = sfcWorkpieceRecord2.CaseNo;
                sfcWorkpieceRecord.PackageNo = sfcWorkpieceRecord2.PackageNo;
                sfcWorkpieceRecord.BoxNo = sfcWorkpieceRecord2.BoxNo;
                sfcWorkpieceRecord.FPBarcode = sfcWorkpieceRecord2.FPBarcode;
                mSFCWorkpieceRecordService.UpdatePo(wLoginUser, sfcWorkpieceRecord, wErrorCode);
            }
            //若为芯子，则更新新工件的成品码、箱条码、出厂条码，参考历史工件信息
            if (sfcAssemblyRecord.ComponentType == PDMComponentTypes.Core.getValue()) {
                sfcWorkpieceRecord.PackageNo = sfcWorkpieceRecord2.PackageNo;
                sfcWorkpieceRecord.BoxNo = sfcWorkpieceRecord2.BoxNo;
                sfcWorkpieceRecord.FPBarcode = sfcWorkpieceRecord2.FPBarcode;
                mSFCWorkpieceRecordService.UpdatePo(wLoginUser, sfcWorkpieceRecord, wErrorCode);
            }
            //若为成品，则更新新工件的箱条码、出厂条码，参考历史工件信息
            if (sfcAssemblyRecord.ComponentType == PDMComponentTypes.Product.getValue()) {
                sfcWorkpieceRecord.BoxNo = sfcWorkpieceRecord2.BoxNo;
                sfcWorkpieceRecord.FPBarcode = sfcWorkpieceRecord2.FPBarcode;
                mSFCWorkpieceRecordService.UpdatePo(wLoginUser, sfcWorkpieceRecord, wErrorCode);
            }
            //历史工件芯子码、成品码、箱条码、出厂条码清空
            sfcWorkpieceRecord2.CaseNo = "";
            sfcWorkpieceRecord2.PackageNo = "";
            sfcWorkpieceRecord2.BoxNo = "";
            sfcWorkpieceRecord2.FPBarcode = "";
            mSFCWorkpieceRecordService.UpdatePo(wLoginUser, sfcWorkpieceRecord2, wErrorCode);
            //⑦替换工件组装记录，换成新的工件
            sfcAssemblyRecord.SourceCode = wNewJobCode;
            mSFCAssemblyRecordService.UpdatePo(wLoginUser, sfcAssemblyRecord, wErrorCode);

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<DMSProcessRecord>> SFC_QueryrocessRecordListByWorkpieceCode(BMSEmployee wLoginUser,
                                                                                          SFCWorkpieceRecord wSFCWorkpieceRecord) {
        ServiceResult<List<DMSProcessRecord>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //根据工件码获取所有经过的工位ID集合
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("ComponentCode", wSFCWorkpieceRecord.Code);
            wParams.put("Type", FPCCheckType.SELF_CHECK.getValue());
            wParams.put("OrderID", wSFCWorkpieceRecord.OrderID);
            List<SFCTaskIPT> sfcTaskIPTS = mSFCTaskIPTService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            if (sfcTaskIPTS == null || sfcTaskIPTS.size() <= 0) {
                wResult.FaultCode += StringUtils.Format("【{0}】未经过任何工位，请检查!", wSFCWorkpieceRecord.Code);
                return wResult;
            }
            //根据工位ID集合，获取设备列表
            List<Integer> wStationIDList =
                    sfcTaskIPTS.stream().map(p -> p.StationID).distinct().collect(Collectors.toList());
            wParams.clear();
            List<FMCStation> fmcStations = mFMCStationService.SelectPOList(wLoginUser, wStationIDList, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            if (fmcStations == null || fmcStations.size() <= 0) {
                wResult.FaultCode += StringUtils.Format("【{0}】工位数据查询失败，请检查!", wSFCWorkpieceRecord.Code);
                return wResult;
            }
            List<Integer> wDeviceIDList = new ArrayList<>();
            for (FMCStation fmcStation : fmcStations) {
                if (fmcStation.DeviceID == null || fmcStation.DeviceID.size() <= 0) {
                    continue;
                }
                wDeviceIDList.addAll(fmcStation.DeviceID);
            }
            //设备ID去重
            wDeviceIDList = wDeviceIDList.stream().distinct().collect(Collectors.toList());
            //遍历设备列表，获取设备采集过程记录集合
            for (int wDeviceID : wDeviceIDList) {
                List<DMSProcessRecord> wDMSProcessRecordList =
                        DMSServiceImpl.getInstance().DMS_SelectProcessRecordList(wLoginUser, -1,
                                -1, "",
                                "", wDeviceID, "", wSFCWorkpieceRecord.Code, 1, new ArrayList<>(Arrays.asList(4, 6, 8)),
                                1, -1, CalendarTool.getBasicDate(), CalendarTool.getBasicDate(), -1,
                                Pagination.getNewMaxSize()).Result;
                if (wDMSProcessRecordList == null || wDMSProcessRecordList.size() <= 0) {
                    continue;
                }
                wResult.Result.addAll(wDMSProcessRecordList);
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_QueryToSpecialTaskList", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCTaskSelf>> SFC_QuerHistoryStartTaskSelfList(BMSEmployee wLoginUser, int shiftType,
                                                                             List<Integer> stationIDList,
                                                                             int wIsUserAll) {
        ServiceResult<List<SFCTaskSelf>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            Calendar wSTime = Calendar.getInstance();
            wSTime.set(wSTime.get(Calendar.YEAR), wSTime.get(Calendar.MONTH), wSTime.get(Calendar.DATE), 0, 0, 0);
            wSTime.add(Calendar.SECOND, -1);

            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("StationID", StringUtils.Join(",", stationIDList));
            wParams.put("StaStartTime", CalendarTool.getBasicDate());
            wParams.put("StaEndTime", wSTime);
            wParams.put("ShiftType", shiftType);
            wParams.put("Active", 1);
            if (wIsUserAll != 1) {
                wParams.put("WorkerID", wLoginUser.ID);
            }
            wParams.put("Status", 2);
            wParams.put("IsRepairPlan", 0);
            wResult.Result = mSFCTaskSelfService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(), wErrorCode);

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_QuerHistoryStartTaskSelfList", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_FinishSameSelfTask(BMSEmployee wLoginUser, SFCTaskSelf wSFCTaskSelf) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("OrderID", wSFCTaskSelf.OrderID);
            wParams.put("RoutePartPointID", wSFCTaskSelf.RoutePartPointID);
            wParams.put("StationID", wSFCTaskSelf.StationID);
            wParams.put("ShiftType", wSFCTaskSelf.ShiftType);
            wParams.put("Status", "1,2,3");
            wParams.put("IsRepairPlan", 0);
            List<SFCTaskSelf> sfcTaskSelves = mSFCTaskSelfService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            if (sfcTaskSelves == null || sfcTaskSelves.size() <= 0) {
                return wResult;
            }

            sfcTaskSelves.removeIf(p -> p.ID == wSFCTaskSelf.ID);
            if (sfcTaskSelves.size() > 0) {
                sfcTaskSelves.forEach(p -> {
                    p.Status = SFCTaskStatus.Done.getValue();
                    p.setUserInfo(wLoginUser);
                });
                mSFCTaskSelfService.UpdatePoList(wLoginUser, sfcTaskSelves, wErrorCode);
            }
            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_DeleteTaskReport(BMSEmployee wLoginUser, SFCTaskReport wSFCTaskReport) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①删除报工单
            mSFCTaskReportService.DeletePO(wLoginUser, wSFCTaskReport, wErrorCode);
            //②若非数量报工，则清除自检单的报工单信息
            if (wSFCTaskReport.ReportMode != FPCTaskReportMode.NUMBER_REPORT.getValue()) {
                Map<String, Object> wParams = new HashMap<String, Object>();
                wParams.put("TaskReportID", wSFCTaskReport.ID);
                List<SFCTaskIPT> sfcTaskIPTS = mSFCTaskIPTService.SelectPOList(wLoginUser, wParams,
                        Pagination.getNewMaxSize(),
                        wErrorCode);
                for (SFCTaskIPT sfcTaskIPT : sfcTaskIPTS) {
                    sfcTaskIPT.IsReported = 0;
                    sfcTaskIPT.TaskReportID = 0;
                    sfcTaskIPT.setUserInfo(wLoginUser);
                    sfcTaskIPT.EditTime = Calendar.getInstance();
                    mSFCTaskIPTService.UpdatePo(wLoginUser, sfcTaskIPT, wErrorCode);
                }
            }
            //③重新计算进度
            TaskTimerUtils.AddTask("UpdatesPlanRealTimeProgress",
                    () -> SFCServiceImpl.getInstance().UpdatesPlanRealTimeProgress(wLoginUser,
                            new ArrayList<>(Collections.singletonList(wSFCTaskReport.TaskSelfID)),
                            new ArrayList<>(Collections.singletonList(wSFCTaskReport.TaskPartPointDayID)), wErrorCode)
            );

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<DMSDeviceLedger>> SFC_QueryDeviceListByWorkstation(BMSEmployee wLoginUser,
                                                                                 int wStationID) {
        ServiceResult<List<DMSDeviceLedger>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("ID", wStationID);
            FMCStation fmcStation = mFMCStationService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (fmcStation == null || fmcStation.ID <= 0) {
                wResult.FaultCode += "未查询到工位信息!";
                return wResult;
            }

            if (fmcStation.DeviceID == null || fmcStation.DeviceID.size() <= 0) {
                wResult.FaultCode += "未查询到工位设备信息!";
                return wResult;
            }

            wParams.clear();
            wResult.Result = mDMSDeviceLedgerService.SelectPOList(wLoginUser, fmcStation.DeviceID, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_QueryToSpecialTaskList", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCTaskReport>> SFC_QueryStatistics(BMSEmployee wLoginUser, Calendar wStartTime,
                                                                  Calendar wEndTime, int wReporterID, String wOrderNo
            , int wProductID, int wStationID) {
        ServiceResult<List<SFCTaskReport>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("CStartTime", wStartTime);
            wParams.put("CEndTime", wEndTime);
            wParams.put("CreatorID", wReporterID);
            wParams.put("OrderNo", wOrderNo);
            wParams.put("StationID", wStationID);
            wResult.Result = mSFCTaskReportService.SelectPOList(wLoginUser, wParams, Pagination.getNewMaxSize(),
                    wErrorCode);
            Map<String, Float> wProductNumberMap = new HashMap<>();
            if (wResult.Result.size() > 0) {
                //按照产品型号分组
                Map<String, List<SFCTaskReport>> wTaskPartIDTaskPartPointMap = wResult.Result.stream()
                        .collect(Collectors.groupingBy(SFCTaskReport::getProductCode));
                wTaskPartIDTaskPartPointMap.forEach((key, value) -> {
                    List<SFCTaskReport> sfcTaskReports = wTaskPartIDTaskPartPointMap.get(key);
                    double sum = sfcTaskReports.stream().mapToDouble(p -> p.ActNum).sum();
                    wProductNumberMap.put(key, (float) sum);
                });
            }
            //添加返回值
            wResult.CustomResult.put("ProductNumberMap", wProductNumberMap);

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_QueryStatistics", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> IPT_UpdateValueList(BMSEmployee wLoginUser, List<IPTValue> wIPTValueList) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①查询待更新的数据集
            List<IPTValue> wToUpdateList = wIPTValueList.stream().filter(p -> p.ID > 0).collect(Collectors.toList());
            //②批量更新
            if (wToUpdateList.size() > 0) {
                IPTValueDAO.getInstance().batchUpdateOrInsert(wLoginUser, wToUpdateList);
            }
            //③查询待插入的数据集
            List<IPTValue> wToInsertList = wIPTValueList.stream().filter(p -> p.ID <= 0).collect(Collectors.toList());
            //④批量插入
            if (wToInsertList.size() > 0) {
                IPTValueDAO.getInstance().batchUpdateOrInsert(wLoginUser, wToInsertList);
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<Integer> SFC_UpdateProgressByReportTask(BMSEmployee wLoginUser, int wTaskReportID) {
        ServiceResult<Integer> wResult = new ServiceResult<>(0);
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("ID", wTaskReportID);
            SFCTaskReport sfcTaskReport = mSFCTaskReportService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (sfcTaskReport == null || sfcTaskReport.ID <= 0) {
                wResult.FaultCode += "未查询到报工单信息!";
                return wResult;
            }

            //更新计划实时进度
            SFCServiceImpl.getInstance().UpdatesPlanRealTimeProgress(wLoginUser,
                    new ArrayList<>(Collections.singletonList(sfcTaskReport.TaskSelfID)),
                    new ArrayList<>(Collections.singletonList(sfcTaskReport.TaskPartPointDayID)), wErrorCode);

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<List<SFCStationInterfaceLog>> SFC_QueryStationInterfaceLogAll(BMSEmployee wLoginUser,
                                                                                       int wStationID,
                                                                                       String wInterfaceType) {
        ServiceResult<List<SFCStationInterfaceLog>> wResult = new ServiceResult<>();
        wResult.Result = new ArrayList<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            wResult.Result = MESConstants.StationInterfaceLogList;
            if (wStationID > 0) {
                wResult.Result =
                        wResult.Result.stream().filter(p -> p.StationID == wStationID).collect(Collectors.toList());
            }
            if (StringUtils.isNotEmpty(wInterfaceType)) {
                wResult.Result =
                        wResult.Result.stream().filter(p -> p.InterfaceType.equals(wInterfaceType)).collect(Collectors.toList());
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error("SFC_QueryStationInterfaceLogAll", e);
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCTaskIPT> SFC_CreateReCheckTaskByWorkpieceNoAndTask(BMSEmployee wLoginUser,
                                                                               String wWorkpieceNo,
                                                                               SFCTaskSelf wSFCTaskSelf) {
        ServiceResult<SFCTaskIPT> wResult = new ServiceResult<>();
        wResult.Result = new SFCTaskIPT();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①根据工件号判断是否已经存在自检单,若存在，查询检验值，返回给前端
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("ComponentCode", wWorkpieceNo);
            wParams.put("OrderID", wSFCTaskSelf.OrderID);
            wParams.put("RoutePartPointID", wSFCTaskSelf.RoutePartPointID);
            wParams.put("Type", FPCCheckType.SELF_CHECK.getValue());
            SFCTaskIPT sfcTaskIPT = mSFCTaskIPTService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (sfcTaskIPT == null || sfcTaskIPT.ID <= 0) {
                wResult.FaultCode += StringUtils.Format("工件【{0}】未做【{1}】工序的自检，请先做自检任务!", wWorkpieceNo,
                        wSFCTaskSelf.RoutePartPointName);
                return wResult;
            }

            //查询复检单
            wParams.clear();
            wParams.put("ComponentCode", wWorkpieceNo);
            wParams.put("OrderID", wSFCTaskSelf.OrderID);
            wParams.put("RoutePartPointID", wSFCTaskSelf.RoutePartPointID);
            wParams.put("Type", FPCCheckType.RE_CHECK.getValue());
            SFCTaskIPT sfcTaskIPT1 = mSFCTaskIPTService.SelectPO(wLoginUser, wParams,
                    wErrorCode);
            if (sfcTaskIPT1 != null && sfcTaskIPT1.ID > 0) {
                wResult.Result = sfcTaskIPT1;

                //查询检验值
                wParams.clear();
                wParams.put("TaskID", sfcTaskIPT1.ID);
                List<IPTValue> wValueList = mIPTValueService.SelectPOList(wLoginUser, wParams,
                        Pagination.getNewMaxSize(),
                        wErrorCode);
                wResult.CustomResult.put("ValueList", wValueList);
                return wResult;
            }

            //查询检验值
            wParams.clear();
            wParams.put("TaskID", sfcTaskIPT.ID);
            List<IPTValue> wValueList = mIPTValueService.SelectPOList(wLoginUser, wParams, Pagination.getNewMaxSize(),
                    wErrorCode);

            //创建复检单
            sfcTaskIPT.TaskPartPointDayID = wSFCTaskSelf.TaskPartPointDayID;
            sfcTaskIPT.TaskSelfID = wSFCTaskSelf.ID;
            sfcTaskIPT.ID = 0;
            sfcTaskIPT.Code = "";
            sfcTaskIPT.Status = SFCTaskStatus.Default.getValue();
            sfcTaskIPT.Type = FPCCheckType.RE_CHECK.getValue();
            int wAffectRows = mSFCTaskIPTService.UpdatePo(wLoginUser, sfcTaskIPT, wErrorCode);
            if (wAffectRows > 0 && sfcTaskIPT.ID > 0) {
                for (IPTValue iptValue : wValueList) {
                    iptValue.ID = 0;
                    iptValue.Code = "";
                    iptValue.TaskID = sfcTaskIPT.ID;
                    iptValue.setUserInfo(wLoginUser);
                }
                IPTValueDAO.getInstance().batchUpdateOrInsert(wLoginUser, wValueList);

                //查询最新的检验值
                wParams.clear();
                wParams.put("TaskID", sfcTaskIPT.ID);
                wValueList = mIPTValueService.SelectPOList(wLoginUser, wParams,
                        Pagination.getNewMaxSize(),
                        wErrorCode);
                wResult.CustomResult.put("ValueList", wValueList);

                wResult.Result = sfcTaskIPT;
            } else {
                wResult.FaultCode += "创建复检单失败!";
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    @Override
    public ServiceResult<SFCWorkpieceExportRecord> SFC_ExportWorkpieceRecord(BMSEmployee wLoginUser, Map<String,
            Object> wParams) {
        ServiceResult<SFCWorkpieceExportRecord> wResult = new ServiceResult<>();
        try {
            OutResult<Integer> wErrorCode = new OutResult<>(0);

            //①根据查询条件获取MD5加密值
            String wMD5 = DesUtil.MD5(JSON.toJSONString(wParams));
            //②判断3分钟内是否已导出，若是，则报错提示
            Map<String, Object> wParams1 = new HashMap<String, Object>();
            wParams1.put("MD5", wMD5);
            List<SFCWorkpieceExportRecord> sfcWorkpieceExportRecords =
                    mSFCWorkpieceExportRecordService.SelectPOList(wLoginUser, wParams1, Pagination.getNewMaxSize(),
                            wErrorCode);
            if (sfcWorkpieceExportRecords.size() > 0) {
                SFCWorkpieceExportRecord sfcWorkpieceExportRecord =
                        sfcWorkpieceExportRecords.stream().max(Comparator.comparing(SFCWorkpieceExportRecord::getCreateTime)).get();
                sfcWorkpieceExportRecord.CreateTime.add(Calendar.MINUTE, 3);
                if (sfcWorkpieceExportRecord.CreateTime.compareTo(Calendar.getInstance()) > 0) {
                    wResult.FaultCode += "该查询条件已导出，请3分钟后再试或直接前往导出记录下载导出文件!";
                    return wResult;
                }
            }
            //③判断是否有5条以上的导出记录正在导出中，若是，则报错提示
            wParams1.clear();
            wParams1.put("Status", SFCWorkpieceExportRecordStatus.Exporting.getValue());
            List<SFCWorkpieceExportRecord> sfcWorkpieceExportRecords1 =
                    mSFCWorkpieceExportRecordService.SelectPOList(wLoginUser, wParams1, Pagination.getNewMaxSize(),
                            wErrorCode);
            if (sfcWorkpieceExportRecords1.size() >= 5) {
                wResult.FaultCode += "有5条或以上导出任务正在导出中，请稍后再试!";
                return wResult;
            }
            //④创建导出记录
            SFCWorkpieceExportRecord sfcWorkpieceExportRecord = new SFCWorkpieceExportRecord(wMD5,
                    SFCWorkpieceExportRecordStatus.ToHand.getValue(), "");
            sfcWorkpieceExportRecord.setUserInfo(wLoginUser);
            mSFCWorkpieceExportRecordService.UpdatePo(wLoginUser, sfcWorkpieceExportRecord,
                    wErrorCode);
            wResult.Result = sfcWorkpieceExportRecord;
            //⑤线程导出
            if (sfcWorkpieceExportRecord.ID > 0) {
                TaskTimerUtils.AddTask("ExportWorkpieceWorkRecord",
                        () -> ExportWorkpieceWorkRecord(wLoginUser, sfcWorkpieceExportRecord, wParams, wErrorCode)
                );
            } else {
                wResult.FaultCode += "创建导出记录失败，请联系系统管理员!";
            }

            wResult.setFaultCode(ExceptionTypes.getEnumType(wErrorCode.Result).getLabel());
        } catch (Exception e) {
            wResult.FaultCode += e.toString();
            log.error(e.toString());
        }
        return wResult;
    }

    /**
     * 导出任务执行
     */
    private void ExportWorkpieceWorkRecord(BMSEmployee wLoginUser, SFCWorkpieceExportRecord wSFCWorkpieceExportRecord,
                                           Map<String, Object> wParams, OutResult<Integer> wErrorCode) {
        try {
            //①更新导出记录状态为`导出中`
            wSFCWorkpieceExportRecord.EditTime = Calendar.getInstance();
            wSFCWorkpieceExportRecord.Status = SFCWorkpieceExportRecordStatus.Exporting.getValue();
            mSFCWorkpieceExportRecordService.UpdatePo(wLoginUser, wSFCWorkpieceExportRecord, wErrorCode);
            //②获取导出数据
            List<MyExcelSheet> wMyExcelSheetList = SFC_GetMyExcelSheetList(wLoginUser, wParams, wErrorCode);
            //③导出执行
            String wDownloadUrl = ExcelUtil.ExportData(wMyExcelSheetList, "工件记录");
            //④更新导出记录状态和导出文件路径
            wSFCWorkpieceExportRecord.EditTime = Calendar.getInstance();
            wSFCWorkpieceExportRecord.Status = SFCWorkpieceExportRecordStatus.Finished.getValue();
            wSFCWorkpieceExportRecord.DownloadUrl = wDownloadUrl;
            mSFCWorkpieceExportRecordService.UpdatePo(wLoginUser, wSFCWorkpieceExportRecord, wErrorCode);
        } catch (Exception ex) {
            log.error("ExportWorkpieceWorkRecord", ex);
        }
    }

    /**
     * 获取导出数据MyExcelSheet数据
     */
    private List<MyExcelSheet> SFC_GetMyExcelSheetList(BMSEmployee wLoginUser, Map<String, Object> wParams,
                                                       OutResult<Integer> wErrorCode) {
        List<MyExcelSheet> wResult = new ArrayList<>();
        try {
            //①根据查询条件获取所有工件记录
            String wMaterialBarcode = StringUtils.parseString(wParams.get("MaterialBarcode"));
            Calendar wStartTime = StringUtils.parseCalendar(wParams.get("CStartTime"));
            Calendar wEndTime = StringUtils.parseCalendar(wParams.get("CEndTime"));
            int wDeviceID = StringUtils.parseInt(wParams.get("DeviceID"));
            int wStationID = StringUtils.parseInt(wParams.get("StationID"));

            ServiceResult<List<SFCWorkpieceRecord>> wServiceResult =
                    SFCServiceImpl.getInstance().SFC_WorkpieceRecordAll(wLoginUser,
                            wMaterialBarcode, wStartTime, wEndTime, wParams, wDeviceID, wStationID,
                            Pagination.getNewMaxSize());
            if (wServiceResult.Result.size() == 0) {
                return wResult;
            }

            List<String> wCodeList = wServiceResult.Result.stream().map(p -> p.Code).collect(Collectors.toList());
            Map<String, Object> wParams1 = new HashMap<String, Object>();
            wParams1.put("ComponentCode", StringUtils.Join(",", wCodeList));
            List<SFCTaskIPT> sfcTaskIPTS = mSFCTaskIPTService.SelectPOList(wLoginUser, wParams1,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            //①作业记录
            MyExcelSheet wMyExcelSheet1 = GetWorkRecordExcelSheet(wLoginUser, wServiceResult.Result, sfcTaskIPTS,
                    wErrorCode);
            wResult.add(wMyExcelSheet1);
            //②物料信息
            MyExcelSheet wMyExcelSheet2 = GetMaterialExcelSheet(wLoginUser, wServiceResult.Result, sfcTaskIPTS,
                    wErrorCode);
            wResult.add(wMyExcelSheet2);
            //③环境参数
            MyExcelSheet wMyExcelSheet3 = GetEnvironmentExcelSheet(wLoginUser, wServiceResult.Result, sfcTaskIPTS,
                    wErrorCode);
            wResult.add(wMyExcelSheet3);
            //④工艺参数
            MyExcelSheet wMyExcelSheet4 = GetCraftExcelSheet(wLoginUser, wServiceResult.Result, sfcTaskIPTS,
                    wErrorCode);
            wResult.add(wMyExcelSheet4);
            //⑤工件组成
            MyExcelSheet wMyExcelSheet5 = GetWorkpieceComposeExcelSheet(wLoginUser, wServiceResult.Result,
                    sfcTaskIPTS, wErrorCode);
            wResult.add(wMyExcelSheet5);
        } catch (Exception ex) {
            log.error("SFC_GetMyExcelSheetList", ex);
        }
        return wResult;
    }

    /**
     * 工件组成
     */
    private MyExcelSheet GetWorkpieceComposeExcelSheet(BMSEmployee wLoginUser,
                                                       List<SFCWorkpieceRecord> wSFCWorkpieceRecordList,
                                                       List<SFCTaskIPT> sfcTaskIPTS, OutResult<Integer> wErrorCode) {
        MyExcelSheet wResult = new MyExcelSheet();
        try {
            wResult.SheetName = "工件组成";
            wResult.TitleName = "";
            wResult.HeaderList = new ArrayList<>(Arrays.asList("订单号", "产品型号", "工件", "产出类型", "芯子码", "成品码", "箱条码",
                    "编辑人", "编辑时间"));
            wResult.DataList = new ArrayList<>();

            if (sfcTaskIPTS.size() == 0) {
                return wResult;
            }

            //根据条码获取工件记录列表
            String wComponentCodes = StringUtils.Join("','",
                    sfcTaskIPTS.stream().map(p -> p.ComponentCode).distinct().collect(Collectors.toList()));
            List<Integer> wIDList = SFCWorkpieceRecordDAO.getInstance().SFC_GetRelaRecordIDList(wLoginUser,
                    wComponentCodes, wErrorCode);
            if (wIDList.size() == 0) {
                return wResult;
            }

            Map<String, Object> wParams = new HashMap<String, Object>();
            List<SFCWorkpieceRecord> sfcWorkpieceRecords = mSFCWorkpieceRecordService.SelectPOList(wLoginUser,
                    wIDList, wParams, Pagination.getNewMaxSize(),
                    wErrorCode);
            sfcWorkpieceRecords.sort(Comparator.comparing(SFCWorkpieceRecord::getCaseNo)
                    .thenComparing(SFCWorkpieceRecord::getPackageNo)
                    .thenComparing(SFCWorkpieceRecord::getBoxNo));
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            for (SFCWorkpieceRecord sfcWorkpieceRecord : sfcWorkpieceRecords) {
                List<String> wRowList =
                        new ArrayList<>(Arrays.asList(sfcWorkpieceRecord.OrderNo
                                , sfcWorkpieceRecord.ProductNo, sfcWorkpieceRecord.Code,
                                PDMComponentTypes.getEnumType(sfcWorkpieceRecord.ComponentType).getLabel(),
                                sfcWorkpieceRecord.CaseNo, sfcWorkpieceRecord.PackageNo, sfcWorkpieceRecord.BoxNo,
                                sfcWorkpieceRecord.EditorName,
                                sdf1.format(sfcWorkpieceRecord.EditTime.getTime())));
                wResult.DataList.add(wRowList);
            }
        } catch (Exception ex) {
            log.error("GetWorkpieceComposeExcelSheet", ex);
        }
        return wResult;
    }

    /**
     * 工艺参数
     */
    private MyExcelSheet GetCraftExcelSheet(BMSEmployee wLoginUser, List<SFCWorkpieceRecord> result,
                                            List<SFCTaskIPT> sfcTaskIPTS, OutResult<Integer> wErrorCode) {
        MyExcelSheet wResult = new MyExcelSheet();
        try {
            wResult.SheetName = "工艺参数";
            wResult.TitleName = "";
            wResult.HeaderList = new ArrayList<>(Arrays.asList("产出类型", "工件号", "订单号", "产品型号", "工单号", "工艺名称", "工序名称",
                    "作业工位",
                    "计划日期", "班次", "设备名称", "参数编号", "参数名称", "参数值", "单位名称"));
            wResult.DataList = new ArrayList<>();

            if (sfcTaskIPTS.size() == 0) {
                return wResult;
            }

            //获取开工检查单
            List<Integer> wTaskSelfIDList =
                    sfcTaskIPTS.stream().map(p -> p.TaskSelfID).distinct().collect(Collectors.toList());
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("TaskSelfID", StringUtils.Join(",", wTaskSelfIDList));
            List<SFCTaskStartCheck> sfcTaskStartChecks = mSFCTaskStartCheckService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            //根据开工检查单，查询环境参数列表
            List<Integer> wTaskStartCheckIDList =
                    sfcTaskStartChecks.stream().map(p -> p.ID).distinct().collect(Collectors.toList());
            wParams.clear();
            wParams.put("TaskStartCheckID", StringUtils.Join(",", wTaskStartCheckIDList));
            wParams.put("ParamType", FPCParamType.PROCESS_PARAMETERS.getValue());
            List<SFCTaskParamItem> sfcTaskParamItems = mSFCTaskParamItemService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);

            Map<Integer, List<SFCTaskParamItem>> wTaskSelfIDParamMap = sfcTaskParamItems.stream()
                    .collect(Collectors.groupingBy(SFCTaskParamItem::getTaskSelfID));

            //获取工位列表
            List<Integer> wStationIDList =
                    sfcTaskIPTS.stream().map(p -> p.StationID).distinct().collect(Collectors.toList());
            wParams.clear();
            List<FMCStation> fmcStations = mFMCStationService.SelectPOList(wLoginUser, wStationIDList, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);

            //检验单排序
            sfcTaskIPTS.sort(Comparator.comparing(SFCTaskIPT::getComponentCode).thenComparing(SFCTaskIPT::getCreateTime));
            //遍历检验单获取数据
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            for (SFCTaskIPT sfcTaskIPT : sfcTaskIPTS) {
                if (!wTaskSelfIDParamMap.containsKey(sfcTaskIPT.TaskSelfID)) {
                    continue;
                }

                String wDeviceName = "";
                Optional<FMCStation> first = fmcStations.stream().filter(p -> p.ID == sfcTaskIPT.StationID).findFirst();
                if (first.isPresent()) {
                    wDeviceName = first.get().DeviceName;
                }

                List<SFCTaskParamItem> sfcTaskParamItems1 = wTaskSelfIDParamMap.get(sfcTaskIPT.TaskSelfID);
                for (SFCTaskParamItem sfcTaskParamItem : sfcTaskParamItems1) {
                    List<String> wRowList =
                            new ArrayList<>(Arrays.asList(PDMComponentTypes.getEnumType(sfcTaskIPT.ComponentType).getLabel()
                                    , sfcTaskIPT.ComponentCode, sfcTaskIPT.OrderNo, sfcTaskIPT.ProductCode,
                                    sfcTaskIPT.TaskSelfCode,
                                    sfcTaskIPT.RoutePartName, sfcTaskIPT.RoutePartPointName, sfcTaskIPT.StationName,
                                    sdf.format(sfcTaskIPT.StationDate.getTime()),
                                    FMCShiftType.getEnumType(sfcTaskIPT.ShiftType).getLabel(),
                                    wDeviceName,
                                    sfcTaskParamItem.ParamCode,
                                    sfcTaskParamItem.ParamName,
                                    sfcTaskParamItem.ParamValue, sfcTaskParamItem.UnitCode));
                    wResult.DataList.add(wRowList);
                }
            }
        } catch (Exception ex) {
            log.error("GetEnvironmentExcelSheet", ex);
        }
        return wResult;
    }

    /**
     * 环境参数
     */
    private MyExcelSheet GetEnvironmentExcelSheet(BMSEmployee wLoginUser,
                                                  List<SFCWorkpieceRecord> wSFCWorkpieceRecordList,
                                                  List<SFCTaskIPT> sfcTaskIPTS, OutResult<Integer> wErrorCode) {
        MyExcelSheet wResult = new MyExcelSheet();
        try {
            wResult.SheetName = "环境参数";
            wResult.TitleName = "";
            wResult.HeaderList = new ArrayList<>(Arrays.asList("产出类型", "工件号", "订单号", "产品型号", "工单号", "工艺名称", "工序名称",
                    "作业工位",
                    "计划日期", "班次", "参数名称", "填写值", "编辑人", "编辑时刻"));
            wResult.DataList = new ArrayList<>();

            if (sfcTaskIPTS.size() == 0) {
                return wResult;
            }

            //获取开工检查单
            List<Integer> wTaskSelfIDList =
                    sfcTaskIPTS.stream().map(p -> p.TaskSelfID).distinct().collect(Collectors.toList());
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("TaskSelfID", StringUtils.Join(",", wTaskSelfIDList));
            List<SFCTaskStartCheck> sfcTaskStartChecks = mSFCTaskStartCheckService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);
            //根据开工检查单，查询环境参数列表
            List<Integer> wTaskStartCheckIDList =
                    sfcTaskStartChecks.stream().map(p -> p.ID).distinct().collect(Collectors.toList());
            wParams.clear();
            wParams.put("TaskStartCheckID", StringUtils.Join(",", wTaskStartCheckIDList));
            wParams.put("ParamType", FPCParamType.ENVIRONMENT_PARAMETERS.getValue());
            List<SFCTaskParamItem> sfcTaskParamItems = mSFCTaskParamItemService.SelectPOList(wLoginUser, wParams,
                    Pagination.getNewMaxSize(),
                    wErrorCode);

            Map<Integer, List<SFCTaskParamItem>> wTaskSelfIDParamMap = sfcTaskParamItems.stream()
                    .collect(Collectors.groupingBy(SFCTaskParamItem::getTaskSelfID));

            //检验单排序
            sfcTaskIPTS.sort(Comparator.comparing(SFCTaskIPT::getComponentCode).thenComparing(SFCTaskIPT::getCreateTime));
            //遍历检验单获取数据
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            for (SFCTaskIPT sfcTaskIPT : sfcTaskIPTS) {
                if (!wTaskSelfIDParamMap.containsKey(sfcTaskIPT.TaskSelfID)) {
                    continue;
                }

                List<SFCTaskParamItem> sfcTaskParamItems1 = wTaskSelfIDParamMap.get(sfcTaskIPT.TaskSelfID);
                for (SFCTaskParamItem sfcTaskParamItem : sfcTaskParamItems1) {
                    List<String> wRowList =
                            new ArrayList<>(Arrays.asList(PDMComponentTypes.getEnumType(sfcTaskIPT.ComponentType).getLabel()
                                    , sfcTaskIPT.ComponentCode, sfcTaskIPT.OrderNo, sfcTaskIPT.ProductCode,
                                    sfcTaskIPT.TaskSelfCode,
                                    sfcTaskIPT.RoutePartName, sfcTaskIPT.RoutePartPointName, sfcTaskIPT.StationName,
                                    sdf.format(sfcTaskIPT.StationDate.getTime()),
                                    FMCShiftType.getEnumType(sfcTaskIPT.ShiftType).getLabel(),
                                    sfcTaskParamItem.ParamName,
                                    sfcTaskParamItem.ParamValue, sfcTaskParamItem.EditorName,
                                    sdf1.format(sfcTaskParamItem.EditTime.getTime())));
                    wResult.DataList.add(wRowList);
                }
            }
        } catch (Exception ex) {
            log.error("GetEnvironmentExcelSheet", ex);
        }
        return wResult;
    }

    /**
     * 获取物料信息
     */
    private MyExcelSheet GetMaterialExcelSheet(BMSEmployee wLoginUser,
                                               List<SFCWorkpieceRecord> wSFCWorkpieceRecordList,
                                               List<SFCTaskIPT> sfcTaskIPTS, OutResult<Integer> wErrorCode) {
        MyExcelSheet wResult = new MyExcelSheet();
        try {
            wResult.SheetName = "物料信息";
            wResult.TitleName = "";
            wResult.HeaderList = new ArrayList<>(Arrays.asList("产出类型", "工件号", "订单号", "产品型号", "工艺名称", "工序名称", "作业工位",
                    "计划日期", "班次", "物料编码", "物料名称", "批次", "原料条码", "编辑人", "编辑时刻"));
            wResult.DataList = new ArrayList<>();

            if (sfcTaskIPTS.size() == 0) {
                return wResult;
            }

            //①查询物料记录
            List<Integer> wTaskIDList = sfcTaskIPTS.stream().map(p -> p.ID).distinct().collect(Collectors.toList());
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("TaskIPTID", StringUtils.Join(",", wTaskIDList));
            List<SFCMaterialLoadingRecord> sfcMaterialLoadingRecords =
                    mSFCMaterialLoadingRecordService.SelectPOList(wLoginUser, wParams, Pagination.getNewMaxSize(),
                            wErrorCode);
            if (sfcMaterialLoadingRecords.size() == 0) {
                return wResult;
            }
            Map<Integer, List<SFCMaterialLoadingRecord>> wTaskMaterialMap = sfcMaterialLoadingRecords.stream()
                    .collect(Collectors.groupingBy(SFCMaterialLoadingRecord::getTaskIPTID));
            //②检验单排序
            sfcTaskIPTS.sort(Comparator.comparing(SFCTaskIPT::getComponentCode).thenComparing(SFCTaskIPT::getCreateTime));
            //③遍历组装数据
            List<SFCMaterialLoadingRecord> sfcMaterialLoadingRecords1;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            for (SFCTaskIPT sfcTaskIPT : sfcTaskIPTS) {
                if (!wTaskMaterialMap.containsKey(sfcTaskIPT.ID)) {
                    continue;
                }

                sfcMaterialLoadingRecords1 = wTaskMaterialMap.get(sfcTaskIPT.ID);
                for (SFCMaterialLoadingRecord sfcMaterialLoadingRecord : sfcMaterialLoadingRecords1) {
                    List<String> wRowList =
                            new ArrayList<>(Arrays.asList(PDMComponentTypes.getEnumType(sfcTaskIPT.ComponentType).getLabel()
                                    , sfcTaskIPT.ComponentCode, sfcTaskIPT.OrderNo, sfcTaskIPT.ProductCode,
                                    sfcTaskIPT.RoutePartName, sfcTaskIPT.RoutePartPointName, sfcTaskIPT.StationName,
                                    sdf.format(sfcTaskIPT.StationDate.getTime()),
                                    FMCShiftType.getEnumType(sfcTaskIPT.ShiftType).getLabel(),
                                    sfcMaterialLoadingRecord.MaterialCode,
                                    sfcMaterialLoadingRecord.MaterialName, sfcMaterialLoadingRecord.BatchNumber,
                                    sfcMaterialLoadingRecord.RawMaterialLot, sfcMaterialLoadingRecord.EditorName,
                                    sdf1.format(sfcMaterialLoadingRecord.EditTime.getTime())));
                    wResult.DataList.add(wRowList);
                }
            }
        } catch (Exception ex) {
            log.error("GetMaterialExcelSheet", ex);
        }
        return wResult;
    }

    /**
     * 获取作业记录
     */
    private MyExcelSheet GetWorkRecordExcelSheet(BMSEmployee wLoginUser,
                                                 List<SFCWorkpieceRecord> wSFCWorkpieceRecordList,
                                                 List<SFCTaskIPT> sfcTaskIPTS, OutResult<Integer> wErrorCode) {
        MyExcelSheet wResult = new MyExcelSheet();
        try {
            wResult.SheetName = "作业记录";
            wResult.TitleName = "";
            wResult.HeaderList = new ArrayList<>(Arrays.asList("产出类型", "工件号", "订单号", "产品型号", "工艺名称", "工序名称", "作业工位",
                    "计划日期", "班次", "作业类型", "结果", "描述", "是否报工", "作业内容"
                    , "填写值", "单位", "编辑人", "编辑时刻"));
            wResult.DataList = new ArrayList<>();

            if (sfcTaskIPTS.size() == 0) {
                return wResult;
            }
            //②根据检验单查询检验值
            List<Integer> wTaskIDList = sfcTaskIPTS.stream().map(p -> p.ID).collect(Collectors.toList());
            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("TaskID", StringUtils.Join(",", wTaskIDList));
            List<IPTValue> iptValues = mIPTValueService.SelectPOList(wLoginUser, wParams, Pagination.getNewMaxSize(),
                    wErrorCode);
            Map<Integer, List<IPTValue>> wTaskIDValueListMap = iptValues.stream()
                    .collect(Collectors.groupingBy(IPTValue::getTaskID));
            //③检验单排序
            sfcTaskIPTS.sort(Comparator.comparing(SFCTaskIPT::getComponentCode).thenComparing(SFCTaskIPT::getCreateTime));
            //④遍历检验单整理数据
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            for (SFCTaskIPT sfcTaskIPT : sfcTaskIPTS) {
                if (!wTaskIDValueListMap.containsKey(sfcTaskIPT.ID)) {
                    continue;
                }

                List<IPTValue> wIPTValueList = wTaskIDValueListMap.get(sfcTaskIPT.ID);
                for (IPTValue iptValue : wIPTValueList) {
                    if (iptValue.RoutePartPointID != sfcTaskIPT.RoutePartPointID) {
                        continue;
                    }
                    List<String> wRowList =
                            new ArrayList<>(Arrays.asList(PDMComponentTypes.getEnumType(sfcTaskIPT.ComponentType).getLabel()
                                    , sfcTaskIPT.ComponentCode, sfcTaskIPT.OrderNo, sfcTaskIPT.ProductCode,
                                    sfcTaskIPT.RoutePartName, sfcTaskIPT.RoutePartPointName, sfcTaskIPT.StationName,
                                    sdf.format(sfcTaskIPT.StationDate.getTime()),
                                    FMCShiftType.getEnumType(sfcTaskIPT.ShiftType).getLabel(),
                                    FPCCheckType.getEnumType(sfcTaskIPT.Type).getLabel(),
                                    SFCCheckResult.getEnumType(sfcTaskIPT.Result).getLabel(), sfcTaskIPT.Description,
                                    sfcTaskIPT.IsReported == 1 ? "是" : "否", iptValue.RouteStepName, iptValue.Value,
                                    iptValue.UnitCode, sfcTaskIPT.EditorName,
                                    sdf1.format(iptValue.EditTime.getTime())));
                    wResult.DataList.add(wRowList);
                }
            }
        } catch (Exception ex) {
            log.error("GetWorkRecordExcelSheet", ex);
        }
        return wResult;
    }
}
